tools: add vio2sf; enable mute channels and add interpolation choice

This commit is contained in:
zeromus 2010-01-08 23:56:14 +00:00
parent 2ef411f641
commit ec367f17be
114 changed files with 54054 additions and 0 deletions

View File

@ -0,0 +1,6 @@
drop directories in here for testing: (projects are configured to put plugins in here)
winamp2
winamp5
tips:
run winamp /NEW myfile.mini2sf to test builds

View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual C++ Express 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foo_input_vio2sf", "foo_input_vio2sf.vcproj", "{22752D82-8F89-4F87-B07E-D254D7BF675A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{22752D82-8F89-4F87-B07E-D254D7BF675A}.Debug|Win32.ActiveCfg = Debug|Win32
{22752D82-8F89-4F87-B07E-D254D7BF675A}.Debug|Win32.Build.0 = Debug|Win32
{22752D82-8F89-4F87-B07E-D254D7BF675A}.Release|Win32.ActiveCfg = Release|Win32
{22752D82-8F89-4F87-B07E-D254D7BF675A}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,258 @@
<?xml version="1.0" encoding="shift_jis"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="foo_input_vio2sf"
ProjectGUID="{22752D82-8F89-4F87-B07E-D254D7BF675A}"
RootNamespace="foo_input_vio2sf"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FOO_INPUT_VIO2SF_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="pfcD.lib foobar2000_SDKD.lib foobar2000_component_clientD.lib shared.lib"
OutputFile="C:\Program Files\foobar2000\components\$(ProjectName).dll"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
EnableIntrinsicFunctions="false"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FOO_INPUT_VIO2SF_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="pfc.lib foobar2000_SDK.lib foobar2000_component_client.lib shared.lib"
OutputFile="$(SolutionDir)$(ProjectName).dll"
LinkIncremental="1"
GenerateManifest="true"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
SetChecksum="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="ソース ファイル"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\src\xsfc\foo_input_xsf.cpp"
>
</File>
<File
RelativePath=".\src\xsfc\foo_input_xsfcfg.cpp"
>
</File>
<File
RelativePath=".\src\loadpe\loadpe.c"
>
</File>
<File
RelativePath=".\src\xsfc\xsfc.cpp"
>
</File>
<File
RelativePath=".\src\xsfc\xsfcfg.cpp"
>
</File>
</Filter>
<Filter
Name="ヘッダー ファイル"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\src\xsfc\leakchk.h"
>
</File>
<File
RelativePath=".\src\loadpe\loadpe.h"
>
</File>
<File
RelativePath=".\src\pversion.h"
>
</File>
<File
RelativePath=".\src\xsfc\tagget.h"
>
</File>
<File
RelativePath=".\src\xsfc\winresx.h"
>
</File>
<File
RelativePath=".\src\xsfc\xsfc.h"
>
</File>
<File
RelativePath=".\src\xsfc\xsfcfg.h"
>
</File>
<File
RelativePath=".\src\xsfc\xsfdrv.h"
>
</File>
</Filter>
<Filter
Name="リソース ファイル"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\src\xsfc\xsfui.rc"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,369 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="foo_xsf8"
ProjectGUID="{02361C60-7E8A-4002-890A-E2B0AC2C91D8}"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\foo_xsf8___Win32_Release"
IntermediateDirectory=".\foo_xsf8___Win32_Release"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\foo_xsf8___Win32_Release/foo_xsf8.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FOO_XSF8_EXPORTS"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\foo_xsf8___Win32_Release/foo_xsf8.pch"
AssemblerListingLocation=".\foo_xsf8___Win32_Release/"
ObjectFile=".\foo_xsf8___Win32_Release/"
ProgramDataBaseFileName=".\foo_xsf8___Win32_Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1041"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="pfc.lib foobar2000_SDK.lib foobar2000_sdk_helpers.lib odbc32.lib odbccp32.lib"
OutputFile="foo_8_vio2sf.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile=".\foo_xsf8___Win32_Release/foo_8_vio2sf.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\foo_xsf8___Win32_Release/foo_8_vio2sf.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\foo_xsf8___Win32_Release/foo_xsf8.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\foo_xsf8___Win32_Debug"
IntermediateDirectory=".\foo_xsf8___Win32_Debug"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\foo_xsf8___Win32_Debug/foo_xsf8.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FOO_XSF8_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\foo_xsf8___Win32_Debug/foo_xsf8.pch"
AssemblerListingLocation=".\foo_xsf8___Win32_Debug/"
ObjectFile=".\foo_xsf8___Win32_Debug/"
ProgramDataBaseFileName=".\foo_xsf8___Win32_Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1041"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="pfcD.lib foobar2000_SDKD.lib foobar2000_sdk_helpersD.lib odbc32.lib odbccp32.lib"
OutputFile="C:\Program Files\foobar2000_8\components\foo_8_vio2sf.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\foo_xsf8___Win32_Debug/foo_8_vio2sf.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\foo_xsf8___Win32_Debug/foo_8_vio2sf.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\foo_xsf8___Win32_Debug/foo_xsf8.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="loadpe"
>
<File
RelativePath="src\loadpe\loadpe.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\loadpe\loadpe.h"
>
</File>
</Filter>
<Filter
Name="xsfc"
>
<File
RelativePath="src\xsfc\foo_input_xsf8.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\foo_input_xsfcfg8.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\leakchk.h"
>
</File>
<File
RelativePath="src\xsfc\tagget.h"
>
</File>
<File
RelativePath="src\xsfc\xsfc.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\xsfc.h"
>
</File>
<File
RelativePath="src\xsfc\xsfcfg.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\xsfcfg.h"
>
</File>
<File
RelativePath="src\xsfc\xsfdrv.h"
>
</File>
<File
RelativePath="src\xsfc\xsfui.rc"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions=""
AdditionalIncludeDirectories="src\xsfc"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions=""
AdditionalIncludeDirectories="src\xsfc"
/>
</FileConfiguration>
</File>
</Filter>
<File
RelativePath="src\pversion.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

376
tools/vio2sf/in_xsf.vcproj Normal file
View File

@ -0,0 +1,376 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="in_xsf"
ProjectGUID="{035B66F9-6D8C-47AA-8CDC-F43DA0BDC1E7}"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug_in_xsf"
IntermediateDirectory=".\Debug_in_xsf"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug_in_xsf/in_xsf.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="src/aosdk,src/aosdk/zlib"
PreprocessorDefinitions="LSB_FIRST;WIN32;_DEBUG;_WINDOWS;_USRDLL;IN_XSF_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug_in_xsf/in_xsf.pch"
AssemblerListingLocation=".\Debug_in_xsf/"
ObjectFile=".\Debug_in_xsf/"
ProgramDataBaseFileName=".\Debug_in_xsf/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1041"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="C:\Program Files\Winamp\Plugins/in_vio2sf.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug_in_xsf/in_vio2sf.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Debug_in_xsf/in_vio2sf.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug_in_xsf/in_xsf.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release_in_xsf"
IntermediateDirectory=".\Release_in_xsf"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release_in_xsf/in_xsf.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IN_XSF_EXPORTS"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release_in_xsf/in_xsf.pch"
AssemblerListingLocation=".\Release_in_xsf/"
ObjectFile=".\Release_in_xsf/"
ProgramDataBaseFileName=".\Release_in_xsf/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1041"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="in_vio2sf.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release_in_xsf/in_vio2sf.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release_in_xsf/in_xsf.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="loadpe"
>
<File
RelativePath="src\loadpe\loadpe.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\loadpe\loadpe.h"
>
</File>
</Filter>
<Filter
Name="xsfc"
>
<File
RelativePath="src\xsfc\in_xsf.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\in_xsfcfg.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\in_xsfcfg.h"
>
</File>
<File
RelativePath="src\xsfc\leakchk.h"
>
</File>
<File
RelativePath="src\xsfc\tagget.h"
>
</File>
<File
RelativePath="src\xsfc\xsfc.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\xsfc.h"
>
</File>
<File
RelativePath="src\xsfc\xsfcfg.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\xsfcfg.h"
>
</File>
<File
RelativePath="src\xsfc\xsfdrv.h"
>
</File>
<File
RelativePath="src\xsfc\xsfui.rc"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions=""
AdditionalIncludeDirectories="src\xsfc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions=""
AdditionalIncludeDirectories="src\xsfc"
/>
</FileConfiguration>
</File>
</Filter>
<File
RelativePath="src\pversion.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

389
tools/vio2sf/in_xsfu.vcproj Normal file
View File

@ -0,0 +1,389 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="in_xsfu"
ProjectGUID="{226CE519-0842-4808-B6F9-C02DE14BB3DC}"
RootNamespace="in_xsfu"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release_in_xsfu"
IntermediateDirectory=".\Release_in_xsfu"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release_in_xsfu/in_xsfu.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="src/aosdk,src/aosdk/zlib,src"
PreprocessorDefinitions="ENABLE_UNICODE_PLUGIN=1;WIN32;NDEBUG;_WINDOWS;_USRDLL;IN_XSF_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release_in_xsfu/in_xsfu.pch"
AssemblerListingLocation=".\Release_in_xsfu/"
ObjectFile=".\Release_in_xsfu/"
ProgramDataBaseFileName=".\Release_in_xsfu/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1041"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="OUTPUT/winamp5/plugins/in_vio2sfu.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release_in_xsfu/in_vio2sfu.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release_in_xsfu/in_xsfu.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine=""
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug_in_xsfu"
IntermediateDirectory=".\Debug_in_xsfu"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug_in_xsfu/in_xsfu.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="src/aosdk,src/aosdk/zlib,src"
PreprocessorDefinitions="ENABLE_UNICODE_PLUGIN=1;LSB_FIRST;WIN32;_DEBUG;_WINDOWS;_USRDLL;IN_XSF_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug_in_xsfu/in_xsfu.pch"
AssemblerListingLocation=".\Debug_in_xsfu/"
ObjectFile=".\Debug_in_xsfu/"
ProgramDataBaseFileName=".\Debug_in_xsfu/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1041"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="OUTPUT/winamp5/plugins/in_vio2sfu.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug_in_xsfu/in_vio2sfu.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Debug_in_xsfu/in_vio2sfu.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug_in_xsfu/in_xsfu.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine=""
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="loadpe"
>
<File
RelativePath="src\loadpe\loadpe.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\loadpe\loadpe.h"
>
</File>
</Filter>
<Filter
Name="xsfc"
>
<File
RelativePath="src\xsfc\in_xsf.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\in_xsfcfg.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\in_xsfcfg.h"
>
</File>
<File
RelativePath="src\xsfc\leakchk.h"
>
</File>
<File
RelativePath="src\xsfc\tagget.h"
>
</File>
<File
RelativePath="src\xsfc\xsfc.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\xsfc.h"
>
</File>
<File
RelativePath="src\xsfc\xsfcfg.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\xsfcfg.h"
>
</File>
<File
RelativePath="src\xsfc\xsfdrv.h"
>
</File>
<File
RelativePath="src\xsfc\xsfui.rc"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions=""
AdditionalIncludeDirectories="src\xsfc"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions=""
AdditionalIncludeDirectories="src\xsfc"
/>
</FileConfiguration>
</File>
</Filter>
<File
RelativePath="src\pversion.h"
>
</File>
<File
RelativePath=".\src\xsfc\xsfui.rh"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

286
tools/vio2sf/kpixsf.vcproj Normal file
View File

@ -0,0 +1,286 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="kpixsf"
ProjectGUID="{45AEABD2-996B-4C43-947C-E43D3A3DF79A}"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug_kpixsf"
IntermediateDirectory=".\Debug_kpixsf"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug_kpixsf/kpixsf.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;KPIXSF_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug_kpixsf/kpixsf.pch"
AssemblerListingLocation=".\Debug_kpixsf/"
ObjectFile=".\Debug_kpixsf/"
ProgramDataBaseFileName=".\Debug_kpixsf/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1041"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib"
OutputFile="C:\usr\bin\kbmed242_beta4\Plugins/vio2sf.kpi"
LinkIncremental="2"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug_kpixsf/vio2sf.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Debug_kpixsf/vio2sf.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug_kpixsf/kpixsf.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release_kpixsf"
IntermediateDirectory=".\Release_kpixsf"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release_kpixsf/kpixsf.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;KPIXSF_EXPORTS"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release_kpixsf/kpixsf.pch"
AssemblerListingLocation=".\Release_kpixsf/"
ObjectFile=".\Release_kpixsf/"
ProgramDataBaseFileName=".\Release_kpixsf/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1041"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib shlwapi.lib"
OutputFile="vio2sf.kpi"
LinkIncremental="1"
SuppressStartupBanner="true"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release_kpixsf/vio2sf.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release_kpixsf/kpixsf.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="loadpe"
>
<File
RelativePath="src\loadpe\loadpe.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\loadpe\loadpe.h"
>
</File>
</Filter>
<Filter
Name="kobarin"
>
<File
RelativePath="src\kobarin\kmp_pi.h"
>
</File>
</Filter>
<Filter
Name="xsfc"
>
<File
RelativePath="src\xsfc\kpixsf.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="src\xsfc\leakchk.h"
>
</File>
<File
RelativePath="src\xsfc\tagget.h"
>
</File>
<File
RelativePath="src\xsfc\xsfdrv.h"
>
</File>
</Filter>
<File
RelativePath="src\pversion.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,65 @@
#ifndef NULLSOFT_WINAMP_DSP_H
#define NULLSOFT_WINAMP_DSP_H
// DSP plugin interface
// notes:
// any window that remains in foreground should optimally pass unused
// keystrokes to the parent (winamp's) window, so that the user
// can still control it. As for storing configuration,
// Configuration data should be stored in <dll directory>\plugin.ini
// (look at the vis plugin for configuration code)
typedef struct winampDSPModule {
char *description; // description
HWND hwndParent; // parent window (filled in by calling app)
HINSTANCE hDllInstance; // instance handle to this DLL (filled in by calling app)
void (*Config)(struct winampDSPModule *this_mod); // configuration dialog (if needed)
int (*Init)(struct winampDSPModule *this_mod); // 0 on success, creates window, etc (if needed)
// modify waveform samples: returns number of samples to actually write
// (typically numsamples, but no more than twice numsamples, and no less than half numsamples)
// numsamples should always be at least 128. should, but I'm not sure
int (*ModifySamples)(struct winampDSPModule *this_mod, short int *samples, int numsamples, int bps, int nch, int srate);
void (*Quit)(struct winampDSPModule *this_mod); // called when unloading
void *userData; // user data, optional
} winampDSPModule;
typedef struct {
int version; // DSP_HDRVER
char *description; // description of library
winampDSPModule* (*getModule)(int); // module retrieval function
int (*sf)(int key); // DSP_HDRVER == 0x21
} winampDSPHeader;
// exported symbols
#ifdef USE_DSP_HDR_HWND
typedef winampDSPHeader* (*winampDSPGetHeaderType)(HWND);
#define DSP_HDRVER 0x22
#else
typedef winampDSPHeader* (*winampDSPGetHeaderType)(HWND);
// header version: 0x20 == 0.20 == winamp 2.0
#define DSP_HDRVER 0x20
#endif
// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)
// which determine if we can uninstall the plugin immediately or on winamp restart
#define DSP_PLUGIN_UNINSTALL_NOW 0x0
#define DSP_PLUGIN_UNINSTALL_REBOOT 0x1
//
// uninstall support was added from 5.0+ and uninstall now support from 5.5+
// it is down to you to ensure that if uninstall now is returned that it will not cause a crash
// (ie don't use if you've been subclassing the main window)
// Version note:
//
// Added passing of Winamp's main hwnd in the call to the exported winampDSPHeader()
// which allows for primarily the use of localisation features with the bundled plugins.
// If you want to use the new version then either you can edit you version of dsp.h or
// you can add USE_DSP_HDR_HWND to your project's defined list or before use of dsp.h
//
#endif

View File

@ -0,0 +1,37 @@
#ifndef NULLSOFT_WINAMP_GEN_H
#define NULLSOFT_WINAMP_GEN_H
#include <windows.h>
#define GEN_INIT_SUCCESS 0
// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)
// which determine if we can uninstall the plugin immediately or on winamp restart
//
// uninstall support was added from 5.0+ and uninstall now support from 5.5+
// it is down to you to ensure that if uninstall now is returned that it will not cause a crash
// (ie don't use if you've been subclassing the main window)
#define GEN_PLUGIN_UNINSTALL_NOW 0x1
#define GEN_PLUGIN_UNINSTALL_REBOOT 0x0
typedef struct {
int version;
char *description;
int (*init)();
void (*config)();
void (*quit)();
HWND hwndParent;
HINSTANCE hDllInstance;
} winampGeneralPurposePlugin;
#define GPPHDR_VER 0x10
#ifdef __cplusplus
extern "C" {
#endif
//extern winampGeneralPurposePlugin *gen_plugins[256];
typedef winampGeneralPurposePlugin * (*winampGeneralPurposePluginGetter)();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,138 @@
#ifndef NULLSOFT_WINAMP_IN2H
#define NULLSOFT_WINAMP_IN2H
#include "out.h"
// note: exported symbol is now winampGetInModule2.
#define IN_UNICODE 0x0F000000
#ifdef UNICODE_INPUT_PLUGIN
#define in_char wchar_t
#define IN_VER (IN_UNICODE | 0x100)
#else
#define in_char char
#define IN_VER 0x100
#endif
#define IN_MODULE_FLAG_USES_OUTPUT_PLUGIN 1
// By default, Winamp assumes that your input plugin wants to use Winamp's EQ, and doesn't do replay gain
// if you handle any of these yourself (EQ, Replay Gain adjustments), then set these flags accordingly
#define IN_MODULE_FLAG_EQ 2 // set this if you do your own EQ
#define IN_MODULE_FLAG_REPLAYGAIN 8 // set this if you adjusted volume for replay gain
// for tracks with no replay gain metadata, you should clear this flag
// UNLESS you handle "non_replaygain" gain adjustment yourself
#define IN_MODULE_FLAG_REPLAYGAIN_PREAMP 16 // use this if you queried for the replay gain preamp parameter and used it
// this parameter is new to 5.54
typedef struct
{
int version; // module type (IN_VER)
char *description; // description of module, with version string
HWND hMainWindow; // winamp's main window (filled in by winamp)
HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp)
char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0"
// May be altered from Config, so the user can select what they want
int is_seekable; // is this stream seekable?
int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :)
// note that this has turned into a "flags" field
// see IN_MODULE_FLAG_*
void (*Config)(HWND hwndParent); // configuration dialog
void (*About)(HWND hwndParent); // about dialog
void (*Init)(); // called at program init
void (*Quit)(); // called at program quit
#define GETFILEINFO_TITLE_LENGTH 2048
void (*GetFileInfo)(const in_char *file, in_char *title, int *length_in_ms); // if file == NULL, current playing is used
#define INFOBOX_EDITED 0
#define INFOBOX_UNCHANGED 1
int (*InfoBox)(const in_char *file, HWND hwndParent);
int (*IsOurFile)(const in_char *fn); // called before extension checks, to allow detection of mms://, etc
// playback stuff
int (*Play)(const in_char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error
void (*Pause)(); // pause stream
void (*UnPause)(); // unpause stream
int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not
void (*Stop)(); // stop (unload) stream
// time stuff
int (*GetLength)(); // get length in ms
int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime()
void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal your thread to seek, which seeks and calls outMod->Flush()..
// volume stuff
void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume
void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan
// in-window builtin vis stuff
void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
// call after opening audio device with max latency in ms and samplerate
void (*SAVSADeInit)(); // call in Stop()
// simple vis supplying mode
void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
// sets the spec data directly from PCM data
// quick and easy way to get vis working :)
// needs at least 576 samples :)
// advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.
int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec))
// use when calling SAAdd()
int (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp
// vis stuff (plug-in)
// simple vis supplying mode
void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data
// quick and easy way to get vis working :)
// needs at least 576 samples :)
// advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.
int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd
int (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in
// call this in Play() to tell the vis plug-ins the current output params.
void (*VSASetInfo)(int srate, int nch); // <-- Correct (benski, dec 2005).. old declaration had the params backwards
// dsp plug-in processing:
// (filled in by winamp, calld by input plug)
// returns 1 if active (which means that the number of samples returned by dsp_dosamples
// could be greater than went in.. Use it to estimate if you'll have enough room in the
// output buffer
int (*dsp_isactive)();
// returns number of samples to output. This can be as much as twice numsamples.
// be sure to allocate enough buffer for samples, then.
int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
// eq stuff
void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.
// info setting (filled in by winamp)
void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)
Out_Module *outMod; // filled in by winamp, optionally used :)
} In_Module;
// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)
// which determine if we can uninstall the plugin immediately or on winamp restart
//
// uninstall support was added from 5.0+ and uninstall now support from 5.5+
// it is down to you to ensure that if uninstall now is returned that it will not cause a crash
// (ie don't use if you've been subclassing the main window)
#define IN_PLUGIN_UNINSTALL_NOW 0x1
#define IN_PLUGIN_UNINSTALL_REBOOT 0x0
#endif

View File

@ -0,0 +1,73 @@
#ifndef NULLSOFT_OUTH
#define NULLSOFT_OUTH
#include <windows.h>
#include <stddef.h>
// ids:
// waveout: 32
// gapless: 64
// xfade: 63
// disk: 33
// dsound: 38
// NULL: 65
// mm2: 69
#if (_MSC_VER <= 1200)
typedef int intptr_t;
#endif
#define OUT_VER 0x10
typedef struct
{
int version; // module version (OUT_VER)
char *description; // description of module, with version string
intptr_t id; // module id. each input module gets its own. non-nullsoft modules should
// be >= 65536.
HWND hMainWindow; // winamp's main window (filled in by winamp)
HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp)
void (*Config)(HWND hwndParent); // configuration dialog
void (*About)(HWND hwndParent); // about dialog
void (*Init)(); // called when loaded
void (*Quit)(); // called when unloaded
int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
// returns >=0 on success, <0 on failure
// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
// ... so don't expect the max latency returned to be what you asked for.
// returns max latency in ms (0 for diskwriters, etc)
// bufferlenms and prebufferms must be in ms. 0 to use defaults.
// prebufferms must be <= bufferlenms
// pass bufferlenms==-666 to tell the output plugin that it's clock is going to be used to sync video
// out_ds turns off silence-eating when -666 is passed
void (*Close)(); // close the ol' output device.
int (*Write)(char *buf, int len);
// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
// 1 returns not able to write (yet). Non-blocking, always.
int (*CanWrite)(); // returns number of bytes possible to write at a given time.
// Never will decrease unless you call Write (or Close, heh)
int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be
// written (i.e. closing while IsPlaying() returns 1 would truncate the song
int (*Pause)(int pause); // returns previous pause state
void (*SetVolume)(int volume); // volume is 0-255
void (*SetPan)(int pan); // pan is -128 to 128
void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms)
// (used for seeking)
int (*GetOutputTime)(); // returns played time in MS
int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)
} Out_Module;
#endif

View File

@ -0,0 +1,56 @@
#ifndef __IPC_PE_H
#define __IPC_PE_H
#define IPC_PE_GETCURINDEX 100 // returns current idx
#define IPC_PE_GETINDEXTOTAL 101 // returns number of items
#define IPC_PE_GETINDEXINFO 102 // (copydata) lpData is of type callbackinfo, callback is called with copydata/fileinfo structure and msg IPC_PE_GETINDEXINFORESULT
#define IPC_PE_GETINDEXINFORESULT 103 // callback message for IPC_PE_GETINDEXINFO
#define IPC_PE_DELETEINDEX 104 // lParam = index
#define IPC_PE_SWAPINDEX 105 // (lParam & 0xFFFF0000) >> 16 = from, (lParam & 0xFFFF) = to
#define IPC_PE_INSERTFILENAME 106 // (copydata) lpData is of type fileinfo
#define IPC_PE_GETDIRTY 107 // returns 1 if the playlist changed since the last IPC_PE_SETCLEAN
#define IPC_PE_SETCLEAN 108 // resets the dirty flag until next modification
#define IPC_PE_GETIDXFROMPOINT 109 // pass a point parm, return a playlist index
#define IPC_PE_SAVEEND 110 // pass index to save from
#define IPC_PE_RESTOREEND 111 // no parm
#define IPC_PE_GETNEXTSELECTED 112 // same as IPC_PLAYLIST_GET_NEXT_SELECTED for the main window
#define IPC_PE_GETSELECTEDCOUNT 113
#define IPC_PE_INSERTFILENAMEW 114 // (copydata) lpData is of type fileinfoW
#define IPC_PE_GETINDEXINFO_TITLE 115 // like IPC_PE_GETINDEXINFO, but writes the title to char file[MAX_PATH] instead of filename
#define IPC_PE_GETINDEXINFORESULT_TITLE 116 // callback message for IPC_PE_GETINDEXINFO
typedef struct {
char file[MAX_PATH];
int index;
} fileinfo;
typedef struct {
wchar_t file[MAX_PATH];
int index;
} fileinfoW;
typedef struct {
HWND callback;
int index;
} callbackinfo;
// the following messages are in_process ONLY
#define IPC_PE_GETINDEXTITLE 200 // lParam = pointer to fileinfo2 struct
#define IPC_PE_GETINDEXTITLEW 201 // lParam = pointer to fileinfo2W struct
#define IPC_PE_GETINDEXINFO_INPROC 202 // lParam = pointer to fileinfo struct
#define IPC_PE_GETINDEXINFOW_INPROC 203 // lParam = pointer to fileinfoW struct
typedef struct {
int fileindex;
char filetitle[256];
char filelength[16];
} fileinfo2;
typedef struct
{
int fileindex;
wchar_t filetitle[256];
wchar_t filelength[16];
} fileinfo2W;
#endif

View File

@ -0,0 +1,436 @@
/*
** Copyright (C) 2003-2008 Nullsoft, Inc.
**
** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
** liable for any damages arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
** alter it and redistribute it freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
**
** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
**
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#ifndef _WA_DLG_H_
#define _WA_DLG_H_
#include "wa_ipc.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
1) gen.bmp has a generic window frame for plugins to use.
its format is similar to the minibrowser's.
In addition gen.bmp includes a font for the titlebar, in both
highlight and no-highlight modes. The font is variable width,
and it uses the first color before the letter A as the delimiter.
The no-highlight form of letter must be the same width as the
highlight form.
2) genex.bmp has button and scrollbar images, as well as some individual
pixels that describe the colors for the dialog. The button and
scrollbar images should be self explanatory (note that the buttons
have 4 pixel sized edges that are not stretched, and the center is
stretched), and the scrollbars do something similar.
The colors start at (48,0) and run every other pixel. The meaning
of each pixel is:
x=48: item background (background to edits, listviews etc)
x=50: item foreground (text color of edit/listview, etc)
x=52: window background (used to set the bg color for the dialog)
x=54: button text color
x=56: window text color
x=58: color of dividers and sunken borders
x=60: selection color for playlists
x=62: listview header background color
x=64: listview header text color
x=66: listview header frame top color
x=68: listview header frame middle color
x=70: listview header frame bottom color
x=72: listview header empty color
x=74: scrollbar foreground color
x=76: scrollbar background color
x=78: inverse scrollbar foreground color
x=80: inverse scrollbar background color
x=82: scrollbar dead area color
x=84: listview/treeview selection bar text color (active)
x=86: listview/treeview selection bar back color (active)
x=88: listview/treeview selection bar text color (inactive)
x=90: listview/treeview selection bar back color (inactive)
x=92: alternate item background
x=94: alternate item foreground
*/
#define DCW_SUNKENBORDER 0x00010000
#define DCW_DIVIDER 0x00020000
enum
{
WADLG_ITEMBG,
WADLG_ITEMFG,
WADLG_WNDBG,
WADLG_BUTTONFG,
WADLG_WNDFG,
WADLG_HILITE,
WADLG_SELCOLOR,
WADLG_LISTHEADER_BGCOLOR,
WADLG_LISTHEADER_FONTCOLOR,
WADLG_LISTHEADER_FRAME_TOPCOLOR,
WADLG_LISTHEADER_FRAME_MIDDLECOLOR,
WADLG_LISTHEADER_FRAME_BOTTOMCOLOR,
WADLG_LISTHEADER_EMPTY_BGCOLOR,
WADLG_SCROLLBAR_FGCOLOR,
WADLG_SCROLLBAR_BGCOLOR,
WADLG_SCROLLBAR_INV_FGCOLOR,
WADLG_SCROLLBAR_INV_BGCOLOR,
WADLG_SCROLLBAR_DEADAREA_COLOR,
WADLG_SELBAR_FGCOLOR,
WADLG_SELBAR_BGCOLOR,
WADLG_INACT_SELBAR_FGCOLOR,
WADLG_INACT_SELBAR_BGCOLOR,
WADLG_ITEMBG2,
WADLG_ITEMFG2,
WADLG_NUM_COLORS
};
typedef enum _WACURSOR // used in IPC_GETSKINCURSORS
{
WACURSOR_VOLUME = 0, // volume & balane
WACURSOR_POSITION = 1, // position
WACURSOR_BTN_WINSHADE = 2, // winshade
WACURSOR_BTN_MINIMIZE = 3, // minimize
WACURSOR_BTN_CLOSE = 4, // close
WACURSOR_MENU = 5, // main menu
WACURSOR_TITLEBAR = 6, // title bar
WACURSOR_SONGNAME = 7,
WACURSOR_NORMAL = 8,
WACURSOR_WINSHADE_BTN_WINSHADE = 9,
WACURSOR_WINSHADE_BTN_MINIMIZE = 10,
WACURSOR_WINSHADE_POSITION = 11,
WACURSOR_WINSHADE_BTN_CLOSE = 12,
WACURSOR_WINSHADE_MENU = 13,
WACURSOR_WINSHADE_NORMAL = 14,
WACURSOR_PL_BTN_WINSHADE = 15,
WACURSOR_PL_BTN_CLOSE = 16,
WACURSOR_PL_TITLEBAR = 17,
WACURSOR_PL_VSCROLL = 18,
WACURSOR_PL_RESIZE = 19,
WACURSOR_PL_NORMAL = 20,
WACURSOR_PL_WINSHADE_BTN_WINSHADE = 21,
WACURSOR_PL_WINSHADE_BTN_CLOSE = 22,
WACURSOR_PL_WINSHADE_HSIZE = 23,
WACURSOR_PL_WINSHADE_NORMAL = 24,
WACURSOR_EQ_SLIDER = 25,
WACURSOR_EQ_BTN_CLOSE = 26,
WACURSOR_EQ_TITLEBAR = 27,
WACURSOR_EQ_NORMAL = 28,
} WACURSOR;
void WADlg_init(HWND hwndWinamp); // call this on init, or on WM_DISPLAYCHANGE
void WADlg_close();
int WADlg_getColor(int idx);
int WADlg_initted();
LRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); //
void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize); // each entry in tab would be the id | DCW_*
HBITMAP WADlg_getBitmap();
/// define WA_DLG_IMPLEMENT in one of your source files before including this .h
// if you are making a media library plugin, you dont need to do this, look at view_ex for
// an example of how to get the function *'s via an IPC message.
#ifdef __cplusplus
}
#endif
#ifdef WA_DLG_IMPLEMENT
static HBRUSH wadlg_lastbrush=0;
static HBITMAP wadlg_bitmap=0; // load this manually
static int wadlg_colors[WADLG_NUM_COLORS];
static int wadlg_defcolors[WADLG_NUM_COLORS]=
{
RGB(0,0,0),
RGB(0,255,0),
RGB(36,36,60),
RGB(57,56,66),
RGB(255,255,255),
RGB(132,148,165),
RGB(0,0,198),
RGB(36*2,36*2,60*2),
RGB(255,255,255),
RGB(36*3,36*3,60*3),
RGB(36,36,60),
RGB(36*0.5,36*0.5,60*0.5),
RGB(36,36,60),
RGB(36*1,36*1,60*1),
RGB(36*1,36*1,60*1),
RGB(121,130,150),
RGB(78,88,110),
RGB(36*1,36*1,60*1),
RGB(255,255,255),
RGB(0,0,180),
RGB(0,255,0),
RGB(0,0,128),
RGB(0,0,0),
RGB(0,255,0),
};
int WADlg_initted()
{
return !!wadlg_bitmap;
}
int WADlg_getColor(int idx)
{
if (idx < 0 || idx >= WADLG_NUM_COLORS) return 0;
return wadlg_colors[idx];
}
HBITMAP WADlg_getBitmap()
{
return wadlg_bitmap;
}
void WADlg_init(HWND hwndWinamp) // call this on init, or on WM_DISPLAYCHANGE
{
if (wadlg_bitmap) DeleteObject(wadlg_bitmap);
wadlg_bitmap = (HBITMAP) SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GET_GENSKINBITMAP);
if (wadlg_bitmap)
{
HDC tmpDC=CreateCompatibleDC(NULL);
HGDIOBJ o=SelectObject(tmpDC,(HGDIOBJ)wadlg_bitmap);
int defbgcol=GetPixel(tmpDC,111,0);
for (int x = 0; x < WADLG_NUM_COLORS; x ++)
{
int a=GetPixel(tmpDC,48+x*2,0);
if (a == CLR_INVALID || a == RGB(0,198,255) || a == defbgcol)
{
//defaults for old skins
if (x == WADLG_SELBAR_FGCOLOR || x == WADLG_INACT_SELBAR_FGCOLOR) a=wadlg_colors[WADLG_WNDFG];
else if (x == WADLG_SELBAR_BGCOLOR || x == WADLG_INACT_SELBAR_BGCOLOR)
{
a=wadlg_colors[WADLG_SELCOLOR];
if (x == WADLG_INACT_SELBAR_BGCOLOR)
a=((a/2)&0x7F7F7F)+(((wadlg_colors[WADLG_WNDBG])/2)&0x7F7F7F);
}
else if (x == WADLG_ITEMBG2)
{
a=wadlg_colors[WADLG_ITEMBG];
}
else if (x == WADLG_ITEMFG2)
{
a=wadlg_colors[WADLG_ITEMFG];
}
else a=wadlg_defcolors[x];
}
wadlg_colors[x]=a;
}
SelectObject(tmpDC,o);
DeleteDC(tmpDC);
}
}
void WADlg_close()
{
if (wadlg_bitmap) DeleteObject(wadlg_bitmap);
wadlg_bitmap=0;
if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush);
wadlg_lastbrush=0;
}
void WADlg_dotLine(HDC hdc, int left, int top, int len, int vert)
{
for(int i=(top&1);i<len-1;i+=2)
{
if(vert)
{
MoveToEx(hdc,left,top+i,NULL);
LineTo(hdc,left,top+i+1);
}
else
{
MoveToEx(hdc,left+i,top,NULL);
LineTo(hdc,left+i+1,top);
}
}
}
LRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_DRAWITEM)
{
DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
if (di->CtlType == ODT_BUTTON) {
wchar_t wt[256];
RECT r;
GetDlgItemTextW(hwndDlg,(INT)wParam,wt,sizeof(wt)/sizeof(*wt));
HDC hdc = CreateCompatibleDC(di->hDC);
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdc, wadlg_bitmap);
r=di->rcItem;
SetStretchBltMode(di->hDC,COLORONCOLOR);
int yoffs = (di->itemState & ODS_SELECTED) ? 15 : 0;
BitBlt(di->hDC,r.left,r.top,4,4,hdc,0,yoffs,SRCCOPY); // top left
StretchBlt(di->hDC,r.left+4,r.top,r.right-r.left-4-4,4,hdc,4,yoffs,47-4-4,4,SRCCOPY); // top center
BitBlt(di->hDC,r.right-4,r.top,4,4,hdc,47-4,yoffs,SRCCOPY); // top right
StretchBlt(di->hDC,r.left,r.top+4,4,r.bottom-r.top-4-4,hdc,0,4+yoffs,4,15-4-4,SRCCOPY); // left edge
StretchBlt(di->hDC,r.right-4,r.top+4,4,r.bottom-r.top-4-4,hdc,47-4,4+yoffs,4,15-4-4,SRCCOPY); // right edge
// center
StretchBlt(di->hDC,r.left+4,r.top+4,r.right-r.left-4-4,r.bottom-r.top-4-4,hdc,4,4+yoffs,47-4-4,15-4-4,SRCCOPY);
BitBlt(di->hDC,r.left,r.bottom-4,4,4,hdc,0,15-4+yoffs,SRCCOPY); // bottom left
StretchBlt(di->hDC,r.left+4,r.bottom-4,r.right-r.left-4-4,4,hdc,4,15-4+yoffs,47-4-4,4,SRCCOPY); // bottom center
BitBlt(di->hDC,r.right-4,r.bottom-4,4,4,hdc,47-4,15-4+yoffs,SRCCOPY); // bottom right
// draw text
SetBkMode(di->hDC,TRANSPARENT);
// this will do a different style for the button text depending on enabled state of the button
COLORREF colour = wadlg_colors[WADLG_BUTTONFG];
if(!IsWindowEnabled(di->hwndItem)){
COLORREF fg = wadlg_colors[WADLG_WNDFG],
bg = wadlg_colors[WADLG_WNDBG];
colour = RGB((GetRValue(fg)+GetRValue(bg))/2,
(GetGValue(fg)+GetGValue(bg))/2,
(GetBValue(fg)+GetBValue(bg))/2);
}
SetTextColor(di->hDC,colour);
if (di->itemState & ODS_SELECTED) {r.left+=2; r.top+=2;}
DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER);
SelectObject(hdc, hbmpOld);
DeleteDC(hdc);
if(GetFocus()==di->hwndItem) {
HPEN hpen, hpenOld;
hpen =CreatePen(PS_SOLID,0,RGB(0,0,0));
hpenOld = (HPEN)SelectObject(di->hDC, hpen);
WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.right-r.left-3,0);
WADlg_dotLine(di->hDC,r.right-3,r.top+2,r.bottom-r.top-3,1);
WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.bottom-r.top-3,1);
WADlg_dotLine(di->hDC,r.left+2,r.bottom-3,r.right-r.left-3,0);
SelectObject(di->hDC, hpenOld);
DeleteObject(hpen);
}
}
}
switch(uMsg)
{
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORDLG:
case WM_CTLCOLORBTN:
case WM_CTLCOLORSTATIC:
case WM_CTLCOLOREDIT:
{
int bgcolor=(uMsg == WM_CTLCOLOREDIT || uMsg == WM_CTLCOLORLISTBOX) ? wadlg_colors[WADLG_ITEMBG] : (uMsg == WM_CTLCOLORBTN ? wadlg_colors[WADLG_ITEMBG] : wadlg_colors[WADLG_WNDBG]);
LOGBRUSH lb={BS_SOLID,GetNearestColor((HDC)wParam,bgcolor)};
if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush);
wadlg_lastbrush=CreateBrushIndirect(&lb);
SetTextColor((HDC)wParam,uMsg == WM_CTLCOLORSTATIC ? wadlg_colors[WADLG_WNDFG] : wadlg_colors[WADLG_ITEMFG]);
SetBkColor((HDC)wParam,lb.lbColor);
return (LRESULT)wadlg_lastbrush;
}
}
return 0;
}
static int RectInRect(RECT *rect1, RECT *rect2)
{
// this has a bias towards true
// this could probably be optimized a lot
return ((rect1->top >= rect2->top && rect1->top <= rect2->bottom) ||
(rect1->bottom >= rect2->top && rect1->bottom <= rect2->bottom) ||
(rect2->top >= rect1->top && rect2->top <= rect1->bottom) ||
(rect2->bottom >= rect1->top && rect2->bottom <= rect1->bottom)) // vertical intersect
&&
((rect1->left >= rect2->left && rect1->left <= rect2->right) ||
(rect1->right >= rect2->left && rect1->right <= rect2->right) ||
(rect2->left >= rect1->left && rect2->left <= rect1->right) ||
(rect2->right >= rect1->left && rect2->right <= rect1->right)) // horiz intersect
;
}
static void WADlg_removeFromRgn(HRGN hrgn, int left, int top, int right, int bottom)
{
HRGN rgn2=CreateRectRgn(left,top,right,bottom);
CombineRgn(hrgn,hrgn,rgn2,RGN_DIFF);
DeleteObject(rgn2);
}
void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize)
{
PAINTSTRUCT ps;
BeginPaint(hwndDlg,&ps);
HRGN hrgn = (ps.fErase) ? CreateRectRgnIndirect(&ps.rcPaint) : NULL;
HPEN pen = CreatePen(PS_SOLID, 0, wadlg_colors[WADLG_HILITE]);
HGDIOBJ o = SelectObject(ps.hdc, pen);
while (tabsize--)
{
RECT r;
int a = *tab++;
GetWindowRect(GetDlgItem(hwndDlg, a & 0xffff),&r);
MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&r, 2);
if (RectInRect(&ps.rcPaint,&r))
{
if ((a & 0xffff0000) == DCW_SUNKENBORDER)
{
MoveToEx(ps.hdc,r.left,r.bottom,NULL);
LineTo(ps.hdc,r.right,r.bottom);
LineTo(ps.hdc,r.right,r.top-1);
if(hrgn)
{
WADlg_removeFromRgn(hrgn,r.left,r.bottom,r.right,r.bottom+1);
WADlg_removeFromRgn(hrgn,r.right,r.top,r.right+1,r.bottom);
}
}
else if ((a & 0xffff0000) == DCW_DIVIDER)
{
if (r.right - r.left < r.bottom - r.top) // vertical
{
int left=(r.left+r.right)/2;
MoveToEx(ps.hdc,left,r.top,NULL);
LineTo(ps.hdc,left,r.bottom+1);
if(hrgn) WADlg_removeFromRgn(hrgn,left,r.top,left+1,r.bottom);
}
else // horiz
{
int top=(r.top+r.bottom)/2;
MoveToEx(ps.hdc,r.left,top,NULL);
LineTo(ps.hdc,r.right+1,top);
if(hrgn) WADlg_removeFromRgn(hrgn,r.left,top,r.right,top+1);
}
}
}
}
SelectObject(ps.hdc, o);
DeleteObject(pen);
if(hrgn)
{
//erase bkgnd while clipping out our own drawn stuff (for flickerless display)
HBRUSH b = CreateSolidBrush(wadlg_colors[WADLG_WNDBG]);
FillRgn(ps.hdc,hrgn,b);
DeleteObject(b);
DeleteObject(hrgn);
}
EndPaint(hwndDlg,&ps);
}
#endif
#endif//_WA_DLG_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
#ifndef KMP_PI_H
#define KMP_PI_H
/*
KbMedia Player Plugin SDK (2005/10/08 )
KbMedia Player
C++ C
http://hp.vector.co.jp/authors/VA015058/source/
使
*/
#define KMPMODULE_VERSION 100 /* KMPMODULE のバージョン */
#define KMP_GETMODULE kmp_GetTestModule /* まだ(いつまで?)テスト版... */
#define SZ_KMP_GETMODULE "kmp_GetTestModule" /* まだ(いつまで?)テスト版... */
#define SZ_KMP_CONFIG "kmp_Config" /* プラグイン設定用v2.38beta2 以降で対応) */
typedef void* HKMP;/* 'K'b'M'edia 'P'layer Plugin の Handle */
typedef struct
{/* オープンしたサウンドデータの情報 */
DWORD dwSamplesPerSec;/* サンプリング周波数(44100, 22050 など) */
DWORD dwChannels; /* チャンネル数( mono = 1, stereo = 2) */
DWORD dwBitsPerSample;/* 量子化ビット数( 8 or 16 or 24 or 32 or -32(32bit float) ) */
DWORD dwLength; /* 曲の長さ(計算不可能な場合は 0xFFFFFFFF */
/* ファイル複数曲dwReserved2 == 1のときは、曲数を 1000 倍した値にする。 */
/* 例えば 10 曲の場合は dwLength == 10000 とする。 */
/* 1ファイル複数曲の場合、曲毎の演奏時間を取得することは出来ない。 */
/* 駄目な仕様でスミマセン */
DWORD dwSeekable; /* シークに対応している場合は 1、しない場合は 0 */
DWORD dwUnitRender; /* Render 関数の第3引数はこの値が渡される(どんな値でも良い場合は 0 */
DWORD dwReserved1; /* 無限ループして演奏終了しない曲の場合に 1, そうでない場合に 0 */
/* Render の呼び出しを繰り返しても演奏終了しない場合に 1 にする */
/* dwReserved1 == 1 の場合、 */
/* ・プレイヤー本体の「単曲リピート」が有効になっている場合は無限ループ */
/* ・dwLength != 0xFFFFFFFF の場合は dwLength だけ再生した後にプレイヤー */
/* 本体によってフェードアウト・演奏終了される */
/* ・dwLength == 0xFFFFFFFF の場合はプレイヤーの設定の「デフォルトの長さ」 */
/* だけ再生した後にフェードアウト・演奏終了される */
/* dwReserved1 == 0 の場合、 */
/* ・Render の戻り値が第3引数(dwSize)より小さい値が返るまで再生される */
DWORD dwReserved2; /* 1ファイル複数曲の場合に 1, 1ファイル1曲のときに 0 */
/* dwReserved2 == 1 の場合、dwLength には曲数を 1000 倍した値を返すこと。 */
/* dwReserved2 == 1 の場合、SetPosition の dwPos に(曲番号 * 1000)が渡される */
/* ようになり、シークは出来なくなるので dwSeek == 0 とすること。 */
/* 現在の仕様では、1ファイル複数曲の拡張子は KbMedia Player 本体で決め打ち */
/* されており、本体が知らない拡張子に対してこの値を 1 にしても正常には動作 */
/* しないし、本体が1ファイル複数曲として扱っている形式に対してこの値を 0 に */
/* しても、やはり正常動作しない(ぉぃ */
/* 駄目な仕様でスミマセン */
}SOUNDINFO;
typedef struct
{
DWORD dwVersion;
/* モジュールのバージョン。プラグインのバージョンではない。 */
/* 必ず KMPMODULE_VERSION(=100) にすること。 */
/* この値が KbMedia Player が期待する値と一致しない場合は、KbMedia Player */
/* によって直ちに FreeLibrary が呼ばれる。 */
/* その場合、Init() も Deinit() も呼ばれないことに注意。 */
DWORD dwPluginVersion;
/* プラグインのバージョン */
/* 対応拡張子が競合するプラグインが見つかった場合は、数字が大きいものを優先的に使う */
const char *pszCopyright;
/* 著作権 */
/* バージョン情報でこの部分の文字列を表示する */
/* NULL にしてもよい */
const char *pszDescription;
/* 説明 */
/* バージョン情報でこの部分の文字列を表示する */
/* NULL にしてもよい */
const char **ppszSupportExts;
/* 対応拡張子の文字列の配列(ピリオド含む) */
/* NULL で終わるようにする */
/* 例ppszSupportExts = {".mp1", ".mp2", ".mp3", "rmp", NULL}; */
/* */
/* ppszSupportExts == {NULL} (ppszSupportExts == NULL は不可)で、かつ Init と Deinit */
/* が 非 NULL の場合は常駐プラグインとして扱われ、KbMedia Player が動作中は常にロード */
/* されたままになる(非公式の機能) */
/* 常駐プラグインとしての動作は Init 呼出し時に開始し、Deinit 呼出し時に終了すること。 */
/* LoadLibrary 時に動作開始、FreeLibrary 時に動作終了は不可) */
/* */
/* 上記以外で対応拡張子がつもない場合、不正なプラグインと見なされ、KbMedia Player */
/* によって直ちに FreeLibrary される。 */
/* その場合は Init() も Deinit() も呼ばれないことに注意。 */
DWORD dwReentrant;
/* 複数ファイルの同時再生が可能な場合は 1, 不可能な場合は 0 */
/* Open の戻り値の HKMP を2つ以上同時に持てない場合に 0 にする */
/* 特別な事情がない限り、出来るだけ dwReentrant == 1 となるように実装するべきである */
/* この値が 0 の場合、2つ目以降のファイルはプレイヤー本体とは別 EXE を経由して開く */
/* ようになる。 */
/* 何らかの理由により、常にプレイヤー本体とは別 EXE でファイルを開くようにしたい場合 */
/* は dwReentrant == 0xFFFFFFFF とすること */
/* 例えば、aaa.kpi と bbb.kpi が ccc.dll に依存し、ccc.dll がノンリエントラントである */
/* 場合は、aaa.kpi も bbb.kpi も dwReentrant == 0xFFFFFFFF になっていた方が望ましい。 */
void (WINAPI *Init)(void);
/* プラグイン初期化。Open 等を呼び出す前に KbMedia Player によって一度だけ呼ばれる。 */
/* 必要ない場合は NULL にしても良い。 */
/* ただし、常駐プラグイン(非公式の機能)の場合は必ず実装すること。 */
/* Init の呼び出しで常駐プラグインを動作開始する。 */
/* LoadLibrary 時に常駐プラグインを動作開始してはいけない。 */
void (WINAPI *Deinit)(void);
/* プラグインの後始末。FreeLibrary の直前に一度だけ呼ばれる。 */
/* Init() を一度も呼ばずに Deinit() を呼ぶ可能性もあることに注意。 */
/* 必要ない場合は NULL にしても良い。 */
/* ただし、常駐プラグイン(非公式の機能)の場合は必ず実装すること。 */
/* Deinit の呼び出しで常駐プラグインを動作終了する */
/* FreeLibrary 時に常駐プラグインを動作終了してはいけない。 */
HKMP (WINAPI *Open)(const char *cszFileName, SOUNDINFO *pInfo);
/* ファイルを開く。必ず実装すること。 */
/* エラーの場合は NULL を返す。 */
/* エラーでない場合は pInfo に適切な情報を入れること。適切な情報が入って */
/* いない場合dwBitsPerSample が 0 など)は KbMedia Player によって直ちに Close */
/* が呼ばれる。 */
/* Open に渡された pInfo->dwSampleRate/dwBitsPerSample/dwChannels の各値が 0 以外の */
/* 場合、可能ならそれに従った形式(または最も近い形式)でファイルを開くようにすること。 */
/* (例えば pInfo->dwBitsPerSample == -32(32bit float) になっている場合、可能なら */
/* 32bit float で、32bit float が不可能でも 32bit int なら対応しているなら 32bit int */
/* で返すなど) */
HKMP (WINAPI *OpenFromBuffer)(const BYTE *Buffer, DWORD dwSize, SOUNDINFO *pInfo);
/* 未使用。NULL にすること。非 NULL でもエラーにはならないが、使用されない。 */
void (WINAPI *Close)(HKMP hKMP);
/* ハンドルを閉じる。必ず実装すること。 */
DWORD (WINAPI *Render)(HKMP hKMP, BYTE* Buffer, DWORD dwSize);
/* Buffer に PCM を入れる。必ず実装すること。 */
/* dwSize は Buffer のサイズのバイト数。(サンプル数ではない) */
/* 戻り値は Buffer に書き込んだバイト数。(サンプル数ではない) */
/* dwSize より小さい値を返したら演奏終了。 */
/* dwSize は SOUNDINFO::dwUnitRender の値が渡される。 */
/* SOUNDINFO::dwUnitRender == 0 の場合は dwSize には任意の値が渡される。 */
/* dwSize はサンプルあたりのバイト数の倍数であることが保証されている) */
DWORD (WINAPI *SetPosition)(HKMP hKMP, DWORD dwPos);
/* シーク。必ず実装すること。 */
/* dwPos はシーク先の再生位置。戻り値はシーク後の再生位置。単位はミリ秒。 */
/* dwPos と戻り値は完全に一致する必要はない。戻り値と本当の再生位置の */
/* 誤差が大きくなる(歌詞との同期再生時に支障をきたす)場合は Open 時に */
/* SOUNDINFO の dwSeekable を 0 にしておくこと。誤差がないか、あっても */
/* 非常に小さい場合は dwSeekable を 1 にしておくこと。戻り値が正確なら */
/* ば、dwPos と戻り値の差が大きくても dwSeekable=1 として良い。 */
/* ただし、実際のシーク先位置が dwPos より後方になることは避けること。 */
/* CueSheet 再生時に問題が起こりやすい) */
/* */
/* シークに全く対応しない場合は、先頭位置に戻して 0 を返すこと。 */
/* */
/* ファイル複数曲SOUNDINFO::dwReserved2 == 1の場合、この関数で選曲 */
/* することになる。曲番号は 1 ベース(曲番号 0 は存在しないで、dwPos */
/* には、曲番号を 1000 倍した値が入る。例えば 5 番目の曲に切り替える場合 */
/* は dwPos == 5000 となる。 */
/* 切り替え後の再生位置は先頭に戻して 0 を返すこと。 */
/* ただし、dwPos == 0 の場合は曲を切り替えずに再生位置を先頭に戻すこと。 */
/* SetPosition が一度も呼ばれていない状態では 1 曲目が選択されているように */
/* すること。 */
/* 切り替えと同時にシークすることは出来ない。(駄目な仕様でスミマセン) */
}KMPMODULE;
typedef KMPMODULE* (WINAPI *pfnGetKMPModule)(void);
/* KMPMODULE* WINAPI kmp_GetTestModule(void); */
/* */
/* KMPMODULE 構造体へのポインタを返す。必ずエクスポートすること。 */
/* この関数はプラグインが LoadLibrary されてから FreeLibrary されるまでの間に */
/* KbMedia Player 本体からは1回だけしか呼ばれない。 */
/* この関数が返した KMPMODULE 構造体のデータメンバは、FreeLibrary されるまで */
/* 変更してはいけない。 */
/* 従って、例えば対応拡張子を設定によって変更されるようにしたい場合、対応拡張子 */
/* の変更が KbMedia Player 本体に認識されるのは、プラグイン再ロード時ということ */
/* になる。 */
typedef DWORD (WINAPI *pfnKmpConfig)(HWND hWnd, DWORD dwVersion, DWORD dwReserved);
/* DWORD WINAPI kmp_Config(HWND hWnd, DWORD dwVersion, DWORD dwReserved); */
/* */
/* KbMedia Player Version 2.38beta2 以降で対応。 */
/* プラグインの設定を行う。特に設定の必要がない場合はエクスポートしなくても良い。 */
/* ・dwVersion/dwReserved ともに 0 が渡される */
/* ・戻り値は現状では 0 を返すのみ */
/* ・HKMP のインスタンスごとの設定は現状では未対応(対応の必要があるのか?) */
/* ・kmp_Config が呼ばれる前に KMPMODULE::Init() が呼ばれる */
/* ・kmp_Config から戻っていない(設定ダイアログを表示している)状態では、 */
/* ・二重に kmp_Config が呼ばれることはない */
/* ・KMPMODULE::Deinit() は呼ばれない */
/* ・FreeLibrary は呼ばれない */
/* ・kmp_Config 呼び出し後、ダイアログを表示したまま直ちにリターンする場合は */
/* この限りではない(その場合はプラグイン側で適切に処理すること) */
/* */
/* 設定はしたいが kmp_Config の実装が面倒、という場合は、プラグインと同じ場所に */
/* プラグインと同名の INI ファイルを置けば、KbMedia Player 本体のプラグイン設定 */
/* ダイアログから INI ファイルを開いて INI ファイルを直接編集出来るようになっている。 */
#endif

View File

@ -0,0 +1,481 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -0,0 +1,563 @@
/*
libloadpe
Copyright (C)2007 Ku-Zu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
loadpe.c
0.5 (2008/03/19)
Added support for WindowsNT4.0/NT3.x/Win32s.
0.4 (2008/02/07)
Leak checker.
0.3 (2008/01/08)
Fixed to protect memory after relocation and importing.
0.2 (2007/12/25)
Fixed not to free depending libraries before DLL_PROCESS_DETACH.
0.1 (2007/12/24)
First release.
*/
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "loadpe.h"
#define MEMORY_CHECK 0
/*
0:Off
1:Check MSVCRT.DLL
2:Check CRTDLL.DLL
*/
#if MEMORY_CHECK
static int chkload = 0;
static int chkcnt = 0;
typedef void * (__cdecl *LPFNMALLOC)(size_t s);
typedef void (__cdecl *LPFNFREE)(void *p);
typedef void * (__cdecl *LPFNREALLOC)(void *p, size_t s);
typedef const char * (__cdecl *LPFNSTRDUP)(const char *s);
typedef void * (__cdecl *LPFNCALLOC)(size_t num, size_t size);
static LPFNMALLOC pmalloc = 0;
static LPFNFREE pfree = 0;
static LPFNREALLOC prealloc = 0;
static LPFNSTRDUP pstrdup = 0;
/*
functions not implemented yet
calloc
_wcsdup,_mbsdup
_getcwd,_wgetcwd
_tempnam,_wtempnam,tmpnam,_wtmpnam
_fullpath,_wfullpath
*/
static void * __cdecl lpe_chk_malloc(size_t s)
{
void *r = (pmalloc) ? pmalloc(s) : 0;
if (r) chkcnt++;
return r;
}
static void __cdecl lpe_chk_free(void *p)
{
if (p)
{
if (pfree)
{
chkcnt--;
pfree(p);
}
}
}
static void * __cdecl lpe_chk_realloc(void *p, size_t s)
{
if (p)
{
if (s)
return prealloc(p, s);
else
lpe_chk_free(p);
}
else
{
if (s)
return lpe_chk_malloc(s);
}
return 0;
}
static const char * __cdecl lpe_chk_strdup(const char *p)
{
char *r = 0;
if (p)
{
size_t s = lstrlenA(p) + 1;
r = lpe_chk_malloc(s);
if (r) MoveMemory(r, p, s);
}
return r;
}
#endif
typedef BOOL (WINAPI *LPFNDLLENTRY)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
typedef struct
{
LPBYTE lpImageBase;
DWORD dwImageSize;
LPFNDLLENTRY lpEntry;
LPBYTE lpImport;
LPBYTE lpExport;
HMODULE *hModules;
} LOADPE;
static WORD getwordle(BYTE *pData)
{
return (WORD)(pData[0] | (((WORD)pData[1]) << 8));
}
static DWORD getdwordle(BYTE *pData)
{
return pData[0] | (((DWORD)pData[1]) << 8) | (((DWORD)pData[2]) << 16) | (((DWORD)pData[3]) << 24);
}
static void setdwordle(LPBYTE lpPtr, DWORD dwDat)
{
lpPtr[0] = (BYTE)((dwDat >> 0) & 0xff);
lpPtr[1] = (BYTE)((dwDat >> 8) & 0xff);
lpPtr[2] = (BYTE)((dwDat >> 16) & 0xff);
lpPtr[3] = (BYTE)((dwDat >> 24) & 0xff);
}
static void setwordle(LPBYTE lpPtr, WORD wDat)
{
lpPtr[0] = (BYTE)((wDat >> 0) & 0xff);
lpPtr[1] = (BYTE)((wDat >> 8) & 0xff);
}
static void *XLoadLibraryH(HANDLE h)
{
LOADPE *ret = NULL;
LOADPE *lpe = NULL;
HMODULE *hModules = NULL;
LPBYTE lpImageBase = 0;
LPBYTE lpHeader = 0;
#define iMZHeaderSize (0x40)
#define iPEHeaderSize (4 + 20 + 224)
DWORD dwOffsetPE;
DWORD dwNumberOfBytesRead;
DWORD dwNumberOfSections;
DWORD dwSizeOfOptionalHeader;
DWORD dwAddressOfEntryPoint;
DWORD dwImageBase;
DWORD dwSizeOfImage;
DWORD dwSizeOfHeaders;
DWORD dwExportRVA;
DWORD dwExportSize;
DWORD dwImportRVA;
DWORD dwImportSize;
DWORD dwRelocationRVA;
DWORD dwRelocationSize;
DWORD dwIATRVA;
DWORD dwIATSize;
LPBYTE lpSectionHeader;
LPBYTE lpSectionHeaderTop;
LPBYTE lpSectionHeaderEnd;
DWORD i;
BYTE peheader[iPEHeaderSize];
switch ((INT_PTR)h)
{
case (INT_PTR)INVALID_HANDLE_VALUE:
return 0;
default:
if (!ReadFile(h, peheader, iMZHeaderSize, &dwNumberOfBytesRead, NULL) || dwNumberOfBytesRead < iMZHeaderSize)
break;
dwOffsetPE = getdwordle(peheader + 0x3c);
if (0xffffffff == SetFilePointer(h, dwOffsetPE, 0, FILE_BEGIN))
break;
if (!ReadFile(h, peheader, iPEHeaderSize, &dwNumberOfBytesRead, NULL) || dwNumberOfBytesRead < iPEHeaderSize)
break;
/* check PE signature */
if (getdwordle(peheader) != 0x00004550)
break;
/* COFF file header */
dwNumberOfSections = getwordle(peheader + 4 + 2);
dwSizeOfOptionalHeader = getwordle(peheader + 4 + 16);
/* optional header standard field */
dwAddressOfEntryPoint = getdwordle(peheader + 4 + 20 + 16);
/* optional header WindowsNT field */
dwImageBase = getdwordle(peheader + 4 + 20 + 28);
dwSizeOfImage = getdwordle(peheader + 4 + 20 + 56);
dwSizeOfHeaders = getdwordle(peheader + 4 + 20 + 60);
/* optinal header data directory */
dwExportRVA = getdwordle(peheader + 4 + 20 + 96);
dwExportSize = getdwordle(peheader + 4 + 20 + 100);
dwImportRVA = getdwordle(peheader + 4 + 20 + 104);
dwImportSize = getdwordle(peheader + 4 + 20 + 108);
dwRelocationRVA = getdwordle(peheader + 4 + 20 + 136);
dwRelocationSize = getdwordle(peheader + 4 + 20 + 140);
dwIATRVA = getdwordle(peheader + 4 + 20 + 192);
dwIATSize = getdwordle(peheader + 4 + 20 + 196);
lpImageBase = VirtualAlloc(0, dwSizeOfImage + dwSizeOfHeaders, MEM_RESERVE, PAGE_NOACCESS);
if (!lpImageBase)
break;
if (0xffffffff == SetFilePointer(h, 0, 0, FILE_BEGIN))
break;
lpHeader = VirtualAlloc(lpImageBase, dwSizeOfHeaders, MEM_COMMIT, PAGE_READWRITE);
if (lpHeader != lpImageBase)
break;
if (!ReadFile(h, lpImageBase, dwSizeOfHeaders, &dwNumberOfBytesRead, NULL) || dwNumberOfBytesRead < dwSizeOfHeaders)
break;
if (0xffffffff == SetFilePointer(h, dwOffsetPE + 4 + 20 + dwSizeOfOptionalHeader, 0, FILE_BEGIN))
break;
lpSectionHeaderTop = lpImageBase + dwOffsetPE + 4 + 20 + dwSizeOfOptionalHeader;
lpSectionHeaderEnd = lpSectionHeaderTop + dwNumberOfSections * 40;
if (lpSectionHeaderEnd >= lpImageBase + dwSizeOfHeaders)
break;
/* load sections */
lpSectionHeader = lpSectionHeaderTop;
for (i = 0; i < dwNumberOfSections; i++)
{
DWORD dwVirtualSize;
DWORD dwVirtualAddress;
DWORD dwSizeOfRawData;
DWORD dwPointerToRawData;
LPBYTE lpSection;
dwVirtualSize = getdwordle(lpSectionHeader + 8);
dwVirtualAddress = getdwordle(lpSectionHeader + 12);
dwSizeOfRawData = getdwordle(lpSectionHeader + 16);
dwPointerToRawData = getdwordle(lpSectionHeader + 20);
lpSection = VirtualAlloc(lpImageBase + dwVirtualAddress, dwVirtualSize, MEM_COMMIT, PAGE_READWRITE);
if (!lpSection)
break;
ZeroMemory(lpImageBase + dwVirtualAddress, dwVirtualSize);
if (0xffffffff == SetFilePointer(h, dwPointerToRawData, 0, FILE_BEGIN))
break;
if (!ReadFile(h, lpImageBase + dwVirtualAddress, dwSizeOfRawData, &dwNumberOfBytesRead, NULL) || dwNumberOfBytesRead < dwSizeOfRawData)
break;
lpSectionHeader += 40;
}
if (lpSectionHeader != lpSectionHeaderEnd) break;
/* resolve relocations */
if (dwRelocationRVA)
{
int iERROR = 0;
LPBYTE lpReloc = lpImageBase + dwRelocationRVA;
while (lpReloc < lpImageBase + dwRelocationRVA + dwRelocationSize)
{
DWORD dwPageRVA = getdwordle(lpReloc + 0);
DWORD dwBlockSize = getdwordle(lpReloc + 4);
for (i = 4; i < (dwBlockSize >> 1); i++)
{
DWORD dwOffset = getwordle(lpReloc + (i << 1));
DWORD dwType = (dwOffset >> 12) & 0xf;
LPBYTE lpRPtr = lpImageBase + dwPageRVA + (dwOffset & 0xfff);
DWORD dwRDat;
switch (dwType)
{
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGHLOW:
dwRDat = getdwordle(lpRPtr);
dwRDat = dwRDat + ((INT_PTR)lpImageBase) - dwImageBase;
setdwordle(lpRPtr, dwRDat);
break;
case IMAGE_REL_BASED_HIGH:
dwRDat = getwordle(lpRPtr) << 16;
dwRDat = dwRDat + ((INT_PTR)lpImageBase) - dwImageBase;
setwordle(lpRPtr, (WORD)((dwRDat >> 16) & 0xffff));
break;
case IMAGE_REL_BASED_LOW:
dwRDat = getwordle(lpRPtr);
dwRDat = dwRDat + ((INT_PTR)lpImageBase) - dwImageBase;
setwordle(lpRPtr, (WORD)(dwRDat & 0xffff));
break;
case IMAGE_REL_BASED_HIGHADJ:
default:
iERROR = 1;
break;
}
}
lpReloc += dwBlockSize;
}
if (iERROR)
break;
}
/* resolve imports */
if (dwImportRVA)
{
int iError = 0;
LPBYTE lpImport;
DWORD dwModuleNumber = 0;
lpImport = lpImageBase + dwImportRVA;
while (getdwordle(lpImport + 12) && getdwordle(lpImport + 16))
{
dwModuleNumber++;
lpImport += 20;
}
hModules = malloc(sizeof(HMODULE) * (dwModuleNumber + 1));
if (!hModules)
break;
i = 0;
lpImport = lpImageBase + dwImportRVA;
while (getdwordle(lpImport + 12) && getdwordle(lpImport + 16))
{
LPCSTR lpszDllName = (LPCSTR)(lpImageBase + getdwordle(lpImport + 12));
LPBYTE lpIAT = lpImageBase + getdwordle(lpImport + 16);
HMODULE hDll = LoadLibraryA(lpszDllName);
if (!hDll)
{
iError = 1;
break;
}
#if MEMORY_CHECK
#if MEMORY_CHECK == 2
if (!lstrcmpi(lpszDllName, "CRTDLL.DLL"))
#else
if (!lstrcmpi(lpszDllName, "MSVCRT.DLL"))
#endif
{
pmalloc = (LPFNMALLOC)GetProcAddress(hDll, "malloc");
pfree = (LPFNFREE)GetProcAddress(hDll, "free");
prealloc = (LPFNREALLOC)GetProcAddress(hDll, "realloc");
pstrdup = (LPFNSTRDUP)GetProcAddress(hDll, "_strdup");
}
#endif
hModules[i++] = hDll;
while (getdwordle(lpIAT))
{
DWORD dwIA = getdwordle(lpIAT);
LPCSTR lpszProcName = (dwIA & 0x80000000) ? MAKEINTRESOURCEA(dwIA & 0x7fffffff) : (LPCSTR)(lpImageBase + dwIA + 2);
DWORD dwProc = (DWORD)(INT_PTR)GetProcAddress(hDll, lpszProcName);
#if MEMORY_CHECK
if (dwProc && dwProc == (DWORD)pmalloc)
dwProc = (DWORD)lpe_chk_malloc;
if (dwProc && dwProc == (DWORD)pfree)
dwProc = (DWORD)lpe_chk_free;
if (dwProc && dwProc == (DWORD)prealloc)
dwProc = (DWORD)lpe_chk_realloc;
if (dwProc && dwProc == (DWORD)pstrdup)
dwProc = (DWORD)lpe_chk_strdup;
#endif
if (dwProc)
setdwordle(lpIAT, dwProc);
else
iError = 1;
lpIAT += 4;
}
lpImport += 20;
}
hModules[i] = 0;
if (iError)
break;
}
lpe = malloc(sizeof(LOADPE));
if (!lpe)
break;
lpe->lpEntry = (LPFNDLLENTRY)(INT_PTR)(dwAddressOfEntryPoint ? lpImageBase + dwAddressOfEntryPoint: 0);
lpe->lpImageBase = lpImageBase;
lpe->lpImport = dwImportRVA ? lpImageBase + dwImportRVA: 0;
lpe->dwImageSize = dwSizeOfImage + dwSizeOfHeaders;
lpe->lpExport = dwExportRVA ? lpImageBase + dwExportRVA: 0;
lpe->hModules = hModules;
/* protect sections */
lpSectionHeader = lpSectionHeaderTop;
for (i = 0; i < dwNumberOfSections; i++)
{
DWORD dwVirtualSize;
DWORD dwVirtualAddress;
DWORD dwCharacteristics;
DWORD fNewProtect;
DWORD fOldProtect;
dwVirtualSize = getdwordle(lpSectionHeader + 8);
dwVirtualAddress = getdwordle(lpSectionHeader + 12);
dwCharacteristics = getdwordle(lpSectionHeader + 36);
switch ((dwCharacteristics >> 29) & 7)
{
default:
case 0: fNewProtect = PAGE_NOACCESS; break;
case 1: fNewProtect = PAGE_EXECUTE; break;
case 2: fNewProtect = PAGE_READONLY; break;
case 3: fNewProtect = PAGE_EXECUTE_READ; break;
case 4:
case 6: fNewProtect = PAGE_READWRITE; break;
case 5:
case 7: fNewProtect = PAGE_EXECUTE_READWRITE; break;
}
VirtualProtect(lpImageBase + dwVirtualAddress, dwVirtualSize, fNewProtect, &fOldProtect);
lpSectionHeader += 40;
}
/* call entry point */
if (lpe->lpEntry)
{
BOOL fResult;
fResult = lpe->lpEntry((HMODULE)lpe->lpImageBase, DLL_PROCESS_ATTACH, 0);
if (fResult == FALSE)
break;
}
ret = lpe;
lpe = 0;
lpImageBase = 0;
hModules = 0;
break;
}
if (hModules)
{
for (i = 0; hModules[i]; i++)
FreeLibrary(hModules[i]);
free(hModules);
}
if (lpImageBase)
{
VirtualFree(lpImageBase, dwSizeOfImage + dwSizeOfHeaders, MEM_DECOMMIT);
VirtualFree(lpImageBase, 0, MEM_RELEASE);
}
if (lpe)
free(lpe);
CloseHandle(h);
#if MEMORY_CHECK
if (ret) chkload++;
#endif
return ret;
}
void *XLoadLibraryA(const char *lpszFileName)
{
HANDLE h = CreateFileA(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
return XLoadLibraryH(h);
}
void *XLoadLibraryW(const WCHAR *lpszFileName)
{
HANDLE h = CreateFileW(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
return XLoadLibraryH(h);
}
void XFreeLibrary(void *hModule)
{
LOADPE *lpe = hModule;
if (lpe)
{
if (lpe->lpEntry)
{
lpe->lpEntry((HMODULE)lpe->lpImageBase, DLL_PROCESS_DETACH, 0);
}
if (lpe->hModules)
{
HMODULE *hModules;
for (hModules = lpe->hModules; *hModules; hModules++)
FreeLibrary(*hModules);
free(lpe->hModules);
}
if (lpe->lpImageBase)
{
VirtualFree(lpe->lpImageBase, lpe->dwImageSize, MEM_DECOMMIT);
VirtualFree(lpe->lpImageBase, 0, MEM_RELEASE);
}
free(lpe);
#if MEMORY_CHECK
if (--chkload == 0)
{
if (chkcnt)
{
char buf[1024];
wsprintfA(buf, "loadpe - memory leak - count %d\n", chkcnt);
OutputDebugStringA(buf);
}
}
#endif
}
}
FARPROC XGetProcAddress(void *hModule, const char *lpfn)
{
LOADPE *lpe = hModule;
if (lpe)
{
if (lpe->lpExport)
{
DWORD dwOrdinal;
DWORD dwOrdinalBase = getdwordle(lpe->lpExport + 20);
DWORD dwAddressTableEntries = getdwordle(lpe->lpExport + 20);
DWORD dwNumberofNamePointers = getdwordle(lpe->lpExport + 24);
LPBYTE lpEAT = lpe->lpImageBase + getdwordle(lpe->lpExport + 28);
LPBYTE lpNPT = lpe->lpImageBase + getdwordle(lpe->lpExport + 32);
LPBYTE lpOT = lpe->lpImageBase + getdwordle(lpe->lpExport + 36);
if (((INT_PTR)lpfn) & (~((INT_PTR)0xffff)))
{
DWORD i;
for (i = 0; i < dwNumberofNamePointers; i++)
{
if (lstrcmpA(lpfn, (LPCSTR)(lpe->lpImageBase + getdwordle(lpNPT + (i << 2)))) == 0)
break;
}
if (i == dwNumberofNamePointers)
return 0;
dwOrdinal = getwordle(lpOT + (i << 1)) + dwOrdinalBase;
}
else
dwOrdinal = (DWORD)(((INT_PTR)lpfn) & 0xffff);
if (dwOrdinal >= dwOrdinalBase && dwOrdinal < dwOrdinalBase + dwAddressTableEntries)
return (FARPROC)(INT_PTR)(lpe->lpImageBase + getdwordle(lpEAT + ((dwOrdinal - dwOrdinalBase) << 3) + 0));
}
}
return 0;
}

View File

@ -0,0 +1,32 @@
/*
libloadpe
Copyright (C)2007 Ku-Zu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef __cplusplus
extern "C" {
#endif
void *XLoadLibraryA(const char *lpszFileName);
void *XLoadLibraryW(const WCHAR *lpszFileName);
void XFreeLibrary(void *hModule);
FARPROC XGetProcAddress(void *hModule, const char *lpfn);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,36 @@
#define XSFDRIVER_VERSIONS "0.22"
#define XSFDRIVER_MODULENAME "vio2sf.bin"
#define XSFDRIVER_ENTRYNAME "XSFSetup"
#define XSFDRIVER_ISSYSTEMTAG(taglen, tag) (((taglen) > 0) && ((tag)[0] == '_') && !(((taglen) > 8) && _strnicmp(tag, "_vio2sf_", 8)))
#define XSFDRIVER_GUID1 { 0xcfa2ca5c, 0xd9a3, 0x49a6, { 0x93, 0x31, 0xf4, 0x09, 0xa2, 0xc1, 0x67, 0xdc } } /* {CFA2CA5C-D9A3-49a6-9331-F409A2C167DC} */
#define XSFDRIVER_GUID2 { 0x5ae3d5fd, 0x0f4b, 0x4ca8, { 0xa9, 0x87, 0xca, 0x60, 0xc0, 0x97, 0x8b, 0x6a } } /* {5AE3D5FD-0F4B-4ca8-A987-CA60C0978B6A} */
#define XSFDRIVER_CHANNELMAP { { 16, "SPU %2d" } , { 0, 0 } }
#define XSFDRIVER_SIMPLENAME "2SF Decoder"
#define DESMUME_VERSIONS "0.8.0"
#define DESMUME_COPYRIGHT "Copyright (C) 2006 yopyop\nCopyright (C) 2006-2007 DeSmuME team"
#define WINAMPPLUGIN_COPYRIGHT DESMUME_COPYRIGHT
#define WINAMPPLUGIN_NAME "2SF Decorder " XSFDRIVER_VERSIONS "/ DeSmuME v" DESMUME_VERSIONS " (x86)"
#define WINAMPPLUGIN_EXTS "2SF;MINI2SF\0Double Screen Sound Format files(*.2SF;*.MINI2SF)\0\0\0"
#define WINAMPPLUGIN_TAG_XSFBY "2sfby"
#define KBMEDIAPLUGIN_VERSION 22
#define KBMEDIAPLUGIN_COPYRIGHT DESMUME_COPYRIGHT
#define KBMEDIAPLUGIN_NAME "2SF plugin " XSFDRIVER_VERSIONS " / DeSmuME v" DESMUME_VERSIONS
#define KBMEDIAPLUGIN_EXTS(n) \
static const char n##_2sfext[] = ".2sf"; \
static const char n##_mini2sfext[] = ".mini2sf"; \
static const char * const (n) [] = { \
n##_2sfext, \
n##_mini2sfext, \
0, \
};
#define FOOBAR2000COMPONENT_NAME "2SF decoder / DeSmuME v" DESMUME_VERSIONS
#define FOOBAR2000COMPONENT_VERSION XSFDRIVER_VERSIONS
#define FOOBAR2000COMPONENT_ABOUT "DeSmuME v" DESMUME_VERSIONS "\n" DESMUME_COPYRIGHT "\n"
#define FOOBAR2000COMPONENT_TYPE "Double Screen Sound Format files"
#define FOOBAR2000COMPONENT_EXTS "*.2SF;*.MINI2SF"
#define FOOBAR2000COMPONENT_EXT_CHECK (!stricmp_utf8(p_extension,"2SF") || !stricmp_utf8(p_extension,"MINI2SF"))
#define FOOBAR2000COMPONENT_ENCODING "2sf"

View File

@ -0,0 +1,33 @@
#ifndef ARM9_H
#define ARM9_H
#include "types.h"
typedef struct {
//ARM9 mem
u8 ARM9_ITCM[0x8000];
u8 ARM9_DTCM[0x4000];
u8 ARM9_WRAM[0x1000000];
u8 MAIN_MEM[0x400000];
u8 ARM9_REG[0x1000000];
u8 ARM9_BIOS[0x8000];
u8 ARM9_VMEM[0x800];
u8 ARM9_ABG[0x80000];
u8 ARM9_BBG[0x20000];
u8 ARM9_AOBJ[0x40000];
u8 ARM9_BOBJ[0x20000];
u8 ARM9_LCD[0xA4000];
u8 ARM9_OAM[0x800];
u8 * ExtPal[2][4];
u8 * ObjExtPal[2][2];
u8 * texPalSlot[4];
const u8 *textureSlotAddr[4];
u8 *blank_memory[0x20000];
} ARM9_struct;
extern ARM9_struct ARM9Mem;
#endif

View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,65 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2007 shash
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "FIFO.h"
void FIFOInit(FIFO * fifo)
{
u32 i;
fifo->begin = 0;
fifo->end = 0;
for(i = 0; i<0x8000; ++i)
fifo->data[i] = 0;
fifo->full = FALSE;
fifo->empty = TRUE;
fifo->error = FALSE;
}
void FIFOAdd(FIFO * fifo, u32 v)
{
if(fifo->full)
{
fifo->error = TRUE;
return;
}
fifo->data[fifo->end] = v;
fifo->end = (fifo->end + 1)& 0x7FFF;
fifo->full = (fifo->end == fifo->begin);
fifo->empty = FALSE;
}
u32 FIFOValue(FIFO * fifo)
{
u32 v;
if(fifo->empty)
{
fifo->error = TRUE;
return 0;
}
v = fifo->data[fifo->begin];
fifo->begin = (fifo->begin + 1)& 0x7FFF;
fifo->empty = (fifo->begin == fifo->end);
return v;
}

View File

@ -0,0 +1,51 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2007 shash
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FIFO_H
#define FIFO_H
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
u32 data[0x8000];
u32 begin;
u32 end;
BOOL full;
BOOL empty;
BOOL error;
} FIFO;
void FIFOInit(FIFO * fifo);
void FIFOAdd(FIFO * fifo, u32 v);
u32 FIFOValue(FIFO * fifo);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,98 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2006-2007 Theo Berkau
Copyright (C) 2007 shash
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// CONTENTS
// INITIALIZATION
// ENABLING / DISABLING LAYERS
// PARAMETERS OF BACKGROUNDS
// PARAMETERS OF ROTOSCALE
// PARAMETERS OF EFFECTS
// PARAMETERS OF WINDOWS
// ROUTINES FOR INSIDE / OUTSIDE WINDOW CHECKS
// PIXEL RENDERING
// BACKGROUND RENDERING -TEXT-
// BACKGROUND RENDERING -ROTOSCALE-
// BACKGROUND RENDERING -HELPER FUNCTIONS-
// SPRITE RENDERING -HELPER FUNCTIONS-
// SPRITE RENDERING
// SCREEN FUNCTIONS
// GRAPHICS CORE
// GPU_ligne
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "MMU.h"
#include "GPU.h"
ARM9_struct ARM9Mem;
NDS_Screen MainScreen;
NDS_Screen SubScreen;
//#define DEBUG_TRI
/*****************************************************************************/
// INITIALIZATION
/*****************************************************************************/
GPU * GPU_Init(u8 l)
{
GPU * g;
if ((g = (GPU *) malloc(sizeof(GPU))) == NULL)
return NULL;
GPU_Reset(g, l);
return g;
}
void GPU_Reset(GPU *g, u8 l)
{
memset(g, 0, sizeof(GPU));
}
void GPU_DeInit(GPU * gpu)
{
if (gpu) free(gpu);
}
int Screen_Init(int coreid) {
MainScreen.gpu = GPU_Init(0);
SubScreen.gpu = GPU_Init(1);
return 0;
}
void Screen_Reset(void) {
GPU_Reset(MainScreen.gpu, 0);
GPU_Reset(SubScreen.gpu, 1);
}
void Screen_DeInit(void) {
GPU_DeInit(MainScreen.gpu);
GPU_DeInit(SubScreen.gpu);
}

View File

@ -0,0 +1,813 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2006-2007 Theo Berkau
Copyright (C) 2007 shash
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef GPU_H
#define GPU_H
#include "ARM9.h"
#include <stdio.h>
#include "mem.h"
#include "registers.h"
#include "FIFO.h"
#include "MMU.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
this structure is for display control,
it holds flags for general display
*******************************************************************************/
#ifdef WORDS_BIGENDIAN
struct _DISPCNT
{
/* 7*/ u8 ForceBlank:1; // A+B:
/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB)
/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels
/* 4*/ u8 OBJ_Tile_1D:1; // A+B: 0=2D (32KB), 1=1D (32..256KB)
/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D
/* 0*/ u8 BG_Mode:3; // A+B:
/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable
/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable
/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable
/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable
/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable
/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable
/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable
/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable
/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5)
/*22*/ u8 OBJ_BMP_1D_Bound:1; // A :
/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B:
/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D)
/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap)
// 0=off (white screen)
// 1=on (normal BG & OBJ layers)
// 2=VRAM display (coreA only)
// 3=RAM display (coreA only, DMA transfers)
/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette
/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette
/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step)
/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step)
};
#else
struct _DISPCNT
{
/* 0*/ u8 BG_Mode:3; // A+B:
/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D
/* 4*/ u8 OBJ_Tile_1D:1; // A+B: 0=2D (32KB), 1=1D (32..256KB)
/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels
/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB)
// 7-15 same as GBA
/* 7*/ u8 ForceBlank:1; // A+B:
/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable
/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable
/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable
/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable
/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable
/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable
/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable
/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable
/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap)
// 0=off (white screen)
// 1=on (normal BG & OBJ layers)
// 2=VRAM display (coreA only)
// 3=RAM display (coreA only, DMA transfers)
/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D)
/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B:
/*22*/ u8 OBJ_BMP_1D_Bound:1; // A :
/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5)
/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step)
/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step)
/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette
/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette
};
#endif
typedef union
{
struct _DISPCNT bits;
u32 val;
} DISPCNT;
#define BGxENABLED(cnt,num) ((num<8)? ((cnt.val>>8) & num):0)
/*******************************************************************************
this structure is for display control of a specific layer,
there are 4 background layers
their priority indicate which one to draw on top of the other
some flags indicate special drawing mode, size, FX
*******************************************************************************/
#ifdef WORDS_BIGENDIAN
struct _BGxCNT
{
/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette
/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic
/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB)
/* 0*/ u8 Priority:2; // 0..3=high..low
/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512
// x/rot/s : 128x128 256x256 512x512 1024x1024
// bmp : 128x128 256x256 512x256 512x512
// large : 512x1024 1024x512 - -
/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2
// BG1 extended palette set 0=set1, 1=set3
// BG2 overflow area wraparound 0=off, 1=wrap
// BG3 overflow area wraparound 0=off, 1=wrap
/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB)
};
#else
struct _BGxCNT
{
/* 0*/ u8 Priority:2; // 0..3=high..low
/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB)
/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic
/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette
/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB)
/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2
// BG1 extended palette set 0=set1, 1=set3
// BG2 overflow area wraparound 0=off, 1=wrap
// BG3 overflow area wraparound 0=off, 1=wrap
/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512
// x/rot/s : 128x128 256x256 512x512 1024x1024
// bmp : 128x128 256x256 512x256 512x512
// large : 512x1024 1024x512 - -
};
#endif
typedef union
{
struct _BGxCNT bits;
u16 val;
} BGxCNT;
/*******************************************************************************
this structure is for background offset
*******************************************************************************/
typedef struct {
u16 BGxHOFS;
u16 BGxVOFS;
} BGxOFS;
/*******************************************************************************
this structure is for rotoscale parameters
*******************************************************************************/
typedef struct {
s16 BGxPA;
s16 BGxPB;
s16 BGxPC;
s16 BGxPD;
s32 BGxX;
s32 BGxY;
} BGxPARMS;
/*******************************************************************************
these structures are for window description,
windows are square regions and can "subclass"
background layers or object layers (i.e window controls the layers)
screen
|
+-- Window0/Window1/OBJwindow/OutOfWindows
|
+-- BG0/BG1/BG2/BG3/OBJ
*******************************************************************************/
typedef union {
struct {
u8 end:8;
u8 start:8;
} bits ;
u16 val;
} WINxDIM;
#ifdef WORDS_BIGENDIAN
typedef struct {
/* 6*/ u8 :2;
/* 5*/ u8 WINx_Effect_Enable:1;
/* 4*/ u8 WINx_OBJ_Enable:1;
/* 3*/ u8 WINx_BG3_Enable:1;
/* 2*/ u8 WINx_BG2_Enable:1;
/* 1*/ u8 WINx_BG1_Enable:1;
/* 0*/ u8 WINx_BG0_Enable:1;
} WINxBIT;
#else
typedef struct {
/* 0*/ u8 WINx_BG0_Enable:1;
/* 1*/ u8 WINx_BG1_Enable:1;
/* 2*/ u8 WINx_BG2_Enable:1;
/* 3*/ u8 WINx_BG3_Enable:1;
/* 4*/ u8 WINx_OBJ_Enable:1;
/* 5*/ u8 WINx_Effect_Enable:1;
/* 6*/ u8 :2;
} WINxBIT;
#endif
#ifdef WORDS_BIGENDIAN
typedef union {
struct {
WINxBIT win0;
WINxBIT win1;
} bits;
struct {
u8 :3;
u8 win0_en:5;
u8 :3;
u8 win1_en:5;
} packed_bits;
struct {
u8 low;
u8 high;
} bytes;
u16 val ;
} WINxCNT ;
#else
typedef union {
struct {
WINxBIT win0;
WINxBIT win1;
} bits;
struct {
u8 win0_en:5;
u8 :3;
u8 win1_en:5;
u8 :3;
} packed_bits;
struct {
u8 low;
u8 high;
} bytes;
u16 val ;
} WINxCNT ;
#endif
/*
typedef struct {
WINxDIM WIN0H;
WINxDIM WIN1H;
WINxDIM WIN0V;
WINxDIM WIN1V;
WINxCNT WININ;
WINxCNT WINOUT;
} WINCNT;
*/
/*******************************************************************************
this structure is for miscellanous settings
//TODO: needs further description
*******************************************************************************/
typedef struct {
u16 MOSAIC;
u16 unused1;
u16 unused2;//BLDCNT;
u16 unused3;//BLDALPHA;
u16 unused4;//BLDY;
u16 unused5;
/*
u16 unused6;
u16 unused7;
u16 unused8;
u16 unused9;
*/
} MISCCNT;
/*******************************************************************************
this structure is for 3D settings
*******************************************************************************/
struct _DISP3DCNT
{
/* 0*/ u8 EnableTexMapping:1; //
/* 1*/ u8 PolygonShading:1; // 0=Toon Shading, 1=Highlight Shading
/* 2*/ u8 EnableAlphaTest:1; // see ALPHA_TEST_REF
/* 3*/ u8 EnableAlphaBlending:1; // see various Alpha values
/* 4*/ u8 EnableAntiAliasing:1; //
/* 5*/ u8 EnableEdgeMarking:1; // see EDGE_COLOR
/* 6*/ u8 FogOnlyAlpha:1; // 0=Alpha and Color, 1=Only Alpha (see FOG_COLOR)
/* 7*/ u8 EnableFog:1; // Fog Master Enable
/* 8*/ u8 FogShiftSHR:4; // 0..10 SHR-Divider (see FOG_OFFSET)
/*12*/ u8 AckColorBufferUnderflow:1; // Color Buffer RDLINES Underflow (0=None, 1=Underflow/Acknowledge)
/*13*/ u8 AckVertexRAMOverflow:1; // Polygon/Vertex RAM Overflow (0=None, 1=Overflow/Acknowledge)
/*14*/ u8 RearPlaneMode:1; // 0=Blank, 1=Bitmap
/*15*/ u8 :1;
/*16*/ u16 :16;
};
typedef union
{
struct _DISP3DCNT bits;
u32 val;
} DISP3DCNT;
/*******************************************************************************
this structure is for capture control (core A only)
source:
http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
*******************************************************************************/
struct _DISPCAPCNT
{
/* 0*/ u8 BlendFactor_A:5; // 0..16 = Blending Factor for Source A
/* 5*/ u8 :3; //
/* 8*/ u8 BlendFactor_B:5; // 0..16 = Blending Factor for Source B
/*13*/ u8 :3; //
/*16*/ u8 VRAM_Write_Block:2; // 0..3 = VRAM A..D
/*18*/ u8 VRAM_Write_Offset:2; // n x 0x08000
/*20*/ u8 Capture_Size:2; // 0=128x128, 1=256x64, 2=256x128, 3=256x192 dots
/*22*/ u8 :2; //
/*24*/ u8 Source_A:1; // 0=Graphics Screen BG+3D+OBJ, 1=3D Screen
/*25*/ u8 Source_B:1; // 0=VRAM, 1=Main Memory Display FIFO
/*26*/ u8 VRAM_Read_Offset:2; // n x 0x08000
/*28*/ u8 :1; //
/*29*/ u8 Capture_Source:2; // 0=Source A, 1=Source B, 2/3=Sources A+B blended
/*31*/ u8 Capture_Enable:1; // 0=Disable/Ready, 1=Enable/Busy
};
typedef union
{
struct _DISPCAPCNT bits;
u32 val;
} DISPCAPCNT;
/*******************************************************************************
this structure holds everything and should be mapped to
* core A : 0x04000000
* core B : 0x04001000
*******************************************************************************/
typedef struct _reg_dispx {
DISPCNT dispx_DISPCNT; // 0x0400x000
u16 dispA_DISPSTAT; // 0x04000004
u16 dispx_VCOUNT; // 0x0400x006
BGxCNT dispx_BGxCNT[4]; // 0x0400x008
BGxOFS dispx_BGxOFS[4]; // 0x0400x010
BGxPARMS dispx_BG2PARMS; // 0x0400x020
BGxPARMS dispx_BG3PARMS; // 0x0400x030
u8 filler[12]; // 0x0400x040
MISCCNT dispx_MISC; // 0x0400x04C
DISP3DCNT dispA_DISP3DCNT; // 0x04000060
DISPCAPCNT dispA_DISPCAPCNT; // 0x04000064
u32 dispA_DISPMMEMFIFO; // 0x04000068
} REG_DISPx ;
#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef max
#define max(a,b) (((a)>(b))?(a):(b))
#endif
typedef BOOL (*fun_gl_Begin) (int screen);
typedef void (*fun_gl_End) (int screen);
// the GUI should use this function prior to all gl calls
// if call to beg succeeds opengl draw
void register_gl_fun(fun_gl_Begin beg,fun_gl_End end);
#define GPU_MAIN 0
#define GPU_SUB 1
/* human readable bitmask names */
#define ADDRESS_STEP_512B 0x00200
#define ADDRESS_STEP_1KB 0x00400
#define ADDRESS_STEP_2KB 0x00800
#define ADDRESS_STEP_4KB 0x01000
#define ADDRESS_STEP_8KB 0x02000
#define ADDRESS_STEP_16KB 0x04000
#define ADDRESS_STEP_32KB 0x08000
#define ADDRESS_STEP_64kB 0x10000
#ifdef WORDS_BIGENDIAN
struct _TILEENTRY
{
/*14*/ unsigned Palette:4;
/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom)
/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right)
/* 0*/ unsigned TileNum:10;
};
#else
struct _TILEENTRY
{
/* 0*/ unsigned TileNum:10;
/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right)
/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom)
/*14*/ unsigned Palette:4;
};
#endif
typedef union
{
struct _TILEENTRY bits;
u16 val;
} TILEENTRY;
struct _ROTOCOORD
{
/* 0*/ unsigned Fraction:8;
/* 8*/ signed Integer:24;
// /*28*/ unsigned :4;
};
typedef union
{
struct _ROTOCOORD bits;
s32 val;
} ROTOCOORD;
/*
this structure is for color representation,
it holds 5 meaningful bits per color channel (red,green,blue)
and 1 meaningful bit for alpha representation
this bit can be unused or used for special FX
*/
struct _COLOR { // abgr x555
#ifdef WORDS_BIGENDIAN
unsigned alpha:1; // sometimes it is unused (pad)
unsigned blue:5;
unsigned green:5;
unsigned red:5;
#else
unsigned red:5;
unsigned green:5;
unsigned blue:5;
unsigned alpha:1; // sometimes it is unused (pad)
#endif
};
struct _COLORx { // abgr x555
unsigned bgr:15;
unsigned alpha:1; // sometimes it is unused (pad)
};
typedef union
{
struct _COLOR bits;
struct _COLORx bitx;
u16 val;
} COLOR;
struct _COLOR32 { // ARGB
unsigned :3;
unsigned blue:5;
unsigned :3;
unsigned green:5;
unsigned :3;
unsigned red:5;
unsigned :7;
unsigned alpha:1; // sometimes it is unused (pad)
};
typedef union
{
struct _COLOR32 bits;
u32 val;
} COLOR32;
#define COLOR_16_32(w,i) \
/* doesnt matter who's 16bit who's 32bit */ \
i.bits.red = w.bits.red; \
i.bits.green = w.bits.green; \
i.bits.blue = w.bits.blue; \
i.bits.alpha = w.bits.alpha;
/*
this structure is for Sprite description,
it holds flags & transformations for 1 sprite
(max 128 OBJs / screen)
ref: http://www.bottledlight.com/ds/index.php/Video/Sprites
*/
typedef struct
{
#ifdef WORDS_BIGENDIAN
// attr0
/* 0*/ unsigned Y:8;
/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal)
/*13*/ unsigned Depth:1; // (0: 16, 1: 256)
/*12*/ unsigned Mosaic:1; // (1: Enabled)
/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap)
/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale)
// attr1
/* 0*/ signed X:9;
/*14*/ unsigned Size:2;
/*13*/ unsigned VFlip:1;
/*12*/ unsigned HFlip:1;
/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index
// attr2
/* 0*/ unsigned TileIndex:10;
/*12*/ unsigned PaletteIndex:4;
/*10*/ unsigned Priority:2;
// attr3
unsigned attr3:16;
#else
// attr0
/* 0*/ unsigned Y:8;
/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale)
/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap)
/*12*/ unsigned Mosaic:1; // (1: Enabled)
/*13*/ unsigned Depth:1; // (0: 16, 1: 256)
/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal)
// attr1
/* 0*/ signed X:9;
/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index
/*12*/ unsigned HFlip:1;
/*13*/ unsigned VFlip:1;
/*14*/ unsigned Size:2;
// attr2
/* 0*/ unsigned TileIndex:10;
/*10*/ unsigned Priority:2;
/*12*/ unsigned PaletteIndex:4;
// attr3
unsigned attr3:16;
#endif
} _OAM_;
typedef struct
{
u16 attr0;
u16 attr1;
u16 attr2;
u16 attr3;
} OAM;
typedef struct
{
s16 x;
s16 y;
} size;
/*
this structure holds information
for rendering.
*/
#define NB_PRIORITIES 4
#define NB_BG 4
typedef struct
{
u8 BGs[NB_BG], nbBGs;
u8 PixelsX[256];
// doh ! yoda says : 256 pixels we can have...
u16 nbPixelsX;
} itemsForPriority_t;
typedef struct _GPU GPU;
struct _GPU
{
// some structs are becoming redundant
// some functions too (no need to recopy some vars as it is done by MMU)
REG_DISPx * dispx_st;
DISPCAPCNT dispCapCnt;
BOOL LayersEnable[5];
itemsForPriority_t itemsForPriority[NB_PRIORITIES];
u8 sprWin[256][256];
#define BGBmpBB BG_bmp_ram
#define BGChBB BG_tile_ram
u8 *(BG_bmp_ram[4]);
u8 *(BG_tile_ram[4]);
u8 *(BG_map_ram[4]);
u8 BGExtPalSlot[4];
u32 BGSize[4][2];
u8 lcd;
u8 core;
u8 dispMode;
u8 vramBlock;
BOOL dispBG[4];
BOOL dispOBJ;
OAM * oam;
u8 * sprMem;
u8 sprBoundary;
u8 sprBMPBoundary;
u8 sprBMPMode;
u32 sprEnable;
u8 WIN0H0;
u8 WIN0H1;
u8 WIN0V0;
u8 WIN0V1;
u8 WIN1H0;
u8 WIN1H1;
u8 WIN1V0;
u8 WIN1V1;
u8 WININ0;
u8 WININ0_SPECIAL;
u8 WININ1;
u8 WININ1_SPECIAL;
u8 WINOUT;
u8 WINOUT_SPECIAL;
u8 WINOBJ;
u8 WINOBJ_SPECIAL;
u8 WIN0_ENABLED;
u8 WIN1_ENABLED;
u8 WINOBJ_ENABLED;
u16 BLDCNT;
u8 BLDALPHA_EVA;
u8 BLDALPHA_EVB;
u8 BLDY_EVY;
u8 MasterBrightMode;
u32 MasterBrightFactor;
BOOL (*setFinalColorSpr)(const GPU *gpu, u32 passing, u8 bgnum, u8 *dst, u16 color, u16 x, u16 y);
BOOL (*setFinalColorBck)(const GPU *gpu, u32 passing, u8 bgnum, u8 *dst, u16 color, u16 x, u16 y);
void (*spriteRender) (GPU * gpu, u16 l, u8 * dst, u8 * prioTab);
};
/*
// normally should have same addresses
static void REG_DISPx_pack_test(GPU * gpu)
{
REG_DISPx * r = gpu->dispx_st;
printf ("%08x %02x\n", r, (long)(&r->dispx_DISPCNT) - (long)r);
printf ("\t%02x\n", (long)(&r->dispA_DISPSTAT) - (long)r);
printf ("\t%02x\n", (long)(&r->dispx_VCOUNT) - (long)r);
printf ("\t%02x\n", (long)(&r->dispx_BGxCNT[0]) - (long)r);
printf ("\t%02x\n", (long)(&r->dispx_BGxOFS[0]) - (long)r);
printf ("\t%02x\n", (long)(&r->dispx_BG2PARMS) - (long)r);
printf ("\t%02x\n", (long)(&r->dispx_BG3PARMS) - (long)r);
printf ("\t%02x\n", (long)(&r->dispx_WINCNT) - (long)r);
printf ("\t%02x\n", (long)(&r->dispx_MISC) - (long)r);
printf ("\t%02x\n", (long)(&r->dispA_DISP3DCNT) - (long)r);
printf ("\t%02x\n", (long)(&r->dispA_DISPCAPCNT) - (long)r);
printf ("\t%02x\n", (long)(&r->dispA_DISPMMEMFIFO) - (long)r);
}
*/
extern u8 GPU_screen[4*256*192];
GPU * GPU_Init(u8 l);
void GPU_Reset(GPU *g, u8 l);
void GPU_DeInit(GPU *);
void textBG(const GPU * gpu, u8 num, u8 * DST); //Draw text based background
void rotBG(GPU * gpu, u8 num, u8 * DST);
void extRotBG(GPU * gpu, u8 num, u8 * DST);
void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab);
void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab);
extern short sizeTab[4][4][2];
extern size sprSizeTab[4][4];
extern s8 mode2type[8][4];
extern void (*modeRender[8][4])(GPU * gpu, u8 num, u16 l, u8 * DST);
typedef struct {
GPU * gpu;
u16 offset;
} NDS_Screen;
extern NDS_Screen MainScreen;
extern NDS_Screen SubScreen;
int Screen_Init(int coreid);
void Screen_Reset(void);
void Screen_DeInit(void);
extern MMU_struct MMU;
#define GFXCORE_DEFAULT -1
#define GFXCORE_DUMMY 0
#define GFXCORE_FULLSCREEN (1 << 0)
typedef struct
{
int id; // ID number for core(see above defines)
const char *Name; // Name of core
int flags; // What features the core supports(full screen, etc.)
int (*Init)(); // Initializes stuff related to core
void (*DeInit)(); // Deinitializes stuff related to core
void (*Resize)(int width, int height, BOOL fullscreen); // Resizes window or fullscreen
void (*OnScreenText)(char *string, ...); // For handling save state messages, etc.
} GraphicsInterface_struct;
extern GraphicsInterface_struct GFXDummy;
void GPU_setVideoProp(GPU *, u32 p);
void GPU_setBGProp(GPU *, u16 num, u16 p);
void GPU_setBLDCNT(GPU *gpu, u16 v) ;
void GPU_setBLDALPHA(GPU *gpu, u16 v) ;
void GPU_setBLDY(GPU *gpu, u16 v) ;
void GPU_setMOSAIC(GPU *gpu, u16 v) ;
void GPU_remove(GPU *, u8 num);
void GPU_addBack(GPU *, u8 num);
int GPU_ChangeGraphicsCore(int coreid);
void GPU_set_DISPCAPCNT(GPU * gpu, u32 val) ;
void GPU_ligne(NDS_Screen * screen, u16 l) ;
void GPU_setMasterBrightness (GPU *gpu, u16 val);
void GPU_setWIN0_H (GPU *gpu, u16 val);
void GPU_setWIN0_H0 (GPU *gpu, u8 val);
void GPU_setWIN0_H1 (GPU *gpu, u8 val);
void GPU_setWIN0_V (GPU *gpu, u16 val);
void GPU_setWIN0_V0 (GPU *gpu, u8 val);
void GPU_setWIN0_V1 (GPU *gpu, u8 val);
void GPU_setWIN1_H (GPU *gpu, u16 val);
void GPU_setWIN1_H0 (GPU *gpu, u8 val);
void GPU_setWIN1_H1 (GPU *gpu, u8 val);
void GPU_setWIN1_V (GPU *gpu, u16 val);
void GPU_setWIN1_V0 (GPU *gpu, u8 val);
void GPU_setWIN1_V1 (GPU *gpu, u8 val);
void GPU_setWININ (GPU *gpu, u16 val);
void GPU_setWININ0 (GPU *gpu, u8 val);
void GPU_setWININ1 (GPU *gpu, u8 val);
void GPU_setWINOUT16(GPU *gpu, u16 val);
void GPU_setWINOUT (GPU *gpu, u8 val);
void GPU_setWINOBJ (GPU *gpu, u8 val);
void GPU_setBLDCNT_LOW (GPU *gpu, u8 val);
void GPU_setBLDCNT_HIGH (GPU *gpu, u8 val);
void GPU_setBLDCNT (GPU *gpu, u16 val);
void GPU_setBLDALPHA (GPU *gpu, u16 val);
void GPU_setBLDALPHA_EVA(GPU *gpu, u8 val);
void GPU_setBLDALPHA_EVB(GPU *gpu, u8 val);
void GPU_setBLDY_EVY (GPU *gpu, u8 val);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,200 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2007 shash
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MMU_H
#define MMU_H
#include "FIFO.h"
#include "dscard.h"
#include "ARM9.h"
#include "mc.h"
#ifdef __cplusplus
extern "C" {
#endif
extern char szRomPath[512];
extern char szRomBaseName[512];
/* theses macros are designed for reading/writing in memory (m is a pointer to memory, like MMU.MMU_MEM[proc], and a is an adress, like 0x04000000 */
#define MEM_8(m, a) (((u8*)(m[((a)>>20)&0xff]))[((a)&0xfff)])
/* theses ones for reading in rom data */
#define ROM_8(m, a) (((u8*)(m))[(a)])
#define IPCFIFO 0
#define MAIN_MEMORY_DISP_FIFO 2
typedef struct {
//ARM7 mem
u8 ARM7_BIOS[0x4000];
u8 ARM7_ERAM[0x10000];
u8 ARM7_REG[0x10000];
u8 ARM7_WIRAM[0x10000];
u8 vram_mode[9];
u8 vScreen;
//Shared ram
u8 SWIRAM[0x8000];
//Card rom & ram
u8 * CART_ROM;
u8 CART_RAM[0x10000];
//Unused ram
u8 UNUSED_RAM[4];
u8 * * MMU_MEM[2];
u32 * MMU_MASK[2];
u8 ARM9_RW_MODE;
FIFO fifos[16];
u32 * MMU_WAIT16[2];
u32 * MMU_WAIT32[2];
u32 DTCMRegion;
u32 ITCMRegion;
u16 timer[2][4];
s32 timerMODE[2][4];
u32 timerON[2][4];
u32 timerRUN[2][4];
u16 timerReload[2][4];
u32 reg_IME[2];
u32 reg_IE[2];
u32 reg_IF[2];
u32 DMAStartTime[2][4];
s32 DMACycle[2][4];
u32 DMACrt[2][4];
BOOL DMAing[2][4];
memory_chip_t fw;
memory_chip_t bupmem;
nds_dscard dscard[2];
u32 CheckTimers;
u32 CheckDMAs;
} MMU_struct;
extern MMU_struct MMU;
struct armcpu_memory_iface {
/** the 32 bit instruction prefetch */
u32 FASTCALL (*prefetch32)( void *data, u32 adr);
/** the 16 bit instruction prefetch */
u16 FASTCALL (*prefetch16)( void *data, u32 adr);
/** read 8 bit data value */
u8 FASTCALL (*read8)( void *data, u32 adr);
/** read 16 bit data value */
u16 FASTCALL (*read16)( void *data, u32 adr);
/** read 32 bit data value */
u32 FASTCALL (*read32)( void *data, u32 adr);
/** write 8 bit data value */
void FASTCALL (*write8)( void *data, u32 adr, u8 val);
/** write 16 bit data value */
void FASTCALL (*write16)( void *data, u32 adr, u16 val);
/** write 32 bit data value */
void FASTCALL (*write32)( void *data, u32 adr, u32 val);
void *data;
};
static void mmu_select_savetype(int type, int *bmemtype, u32 *bmemsize) {
if (type<0 || type > 5) return;
*bmemtype=save_types[type][0];
*bmemsize=save_types[type][1];
mc_realloc(&MMU.bupmem, *bmemtype, *bmemsize);
}
void MMU_Init(void);
void MMU_DeInit(void);
void MMU_clearMem( void);
void MMU_setRom(u8 * rom, u32 mask);
void MMU_unsetRom( void);
/**
* Memory reading
*/
u8 FASTCALL MMU_read8(u32 proc, u32 adr);
u16 FASTCALL MMU_read16(u32 proc, u32 adr);
u32 FASTCALL MMU_read32(u32 proc, u32 adr);
#ifdef MMU_ENABLE_ACL
u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access);
u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access);
u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access);
#else
#define MMU_read8_acl(proc,adr,access) MMU_read8(proc,adr)
#define MMU_read16_acl(proc,adr,access) MMU_read16(proc,adr)
#define MMU_read32_acl(proc,adr,access) MMU_read32(proc,adr)
#endif
/**
* Memory writing
*/
void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val);
void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val);
void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val);
#ifdef MMU_ENABLE_ACL
void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val);
void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val);
void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val);
#else
#define MMU_write8_acl MMU_write8
#define MMU_write16_acl MMU_write16
#define MMU_write32_acl MMU_write32
#endif
void FASTCALL MMU_doDMA(u32 proc, u32 num);
/*
* The base ARM memory interfaces
*/
extern struct armcpu_memory_iface arm9_base_memory_iface;
extern struct armcpu_memory_iface arm7_base_memory_iface;
extern struct armcpu_memory_iface arm9_direct_memory_iface;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,748 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <stdlib.h>
#include "NDSSystem.h"
#include "MMU.h"
//#include "cflash.h"
//#include "ROMReader.h"
/* the count of bytes copied from the firmware into memory */
#define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70
NDSSystem nds;
static u32
calc_CRC16( u32 start, const u8 *data, int count) {
int i,j;
u32 crc = start & 0xffff;
static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
for(i = 0; i < count; i++)
{
crc = crc ^ data[i];
for(j = 0; j < 8; j++) {
int do_bit = 0;
if ( crc & 0x1)
do_bit = 1;
crc = crc >> 1;
if ( do_bit) {
crc = crc ^ (val[j] << (7-j));
}
}
}
return crc;
}
static int
copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data) {
/*
* Determine which of the two user settings in the firmware is the current
* and valid one and then copy this into the destination buffer.
*
* The current setting will have a greater count.
* Settings are only valid if its CRC16 is correct.
*/
int user1_valid = 0;
int user2_valid = 0;
u32 user_settings_offset;
u32 fw_crc;
u32 crc;
int copy_good = 0;
user_settings_offset = fw_data[0x20];
user_settings_offset |= fw_data[0x21] << 8;
user_settings_offset <<= 3;
if ( user_settings_offset <= 0x3FE00) {
s32 copy_settings_offset = -1;
crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset],
NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
fw_crc = fw_data[user_settings_offset + 0x72];
fw_crc |= fw_data[user_settings_offset + 0x73] << 8;
if ( crc == fw_crc) {
user1_valid = 1;
}
crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100],
NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
fw_crc = fw_data[user_settings_offset + 0x100 + 0x72];
fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8;
if ( crc == fw_crc) {
user2_valid = 1;
}
if ( user1_valid) {
if ( user2_valid) {
u16 count1, count2;
count1 = fw_data[user_settings_offset + 0x70];
count1 |= fw_data[user_settings_offset + 0x71] << 8;
count2 = fw_data[user_settings_offset + 0x100 + 0x70];
count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8;
if ( count2 > count1) {
copy_settings_offset = user_settings_offset + 0x100;
}
else {
copy_settings_offset = user_settings_offset;
}
}
else {
copy_settings_offset = user_settings_offset;
}
}
else if ( user2_valid) {
/* copy the second user settings */
copy_settings_offset = user_settings_offset + 0x100;
}
if ( copy_settings_offset > 0) {
memcpy( dest_buffer, &fw_data[copy_settings_offset],
NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
copy_good = 1;
}
}
return copy_good;
}
#ifdef GDB_STUB
int NDS_Init( struct armcpu_memory_iface *arm9_mem_if,
struct armcpu_ctrl_iface **arm9_ctrl_iface,
struct armcpu_memory_iface *arm7_mem_if,
struct armcpu_ctrl_iface **arm7_ctrl_iface) {
#else
int NDS_Init( void) {
#endif
nds.ARM9Cycle = 0;
nds.ARM7Cycle = 0;
nds.cycles = 0;
MMU_Init();
nds.nextHBlank = 3168;
nds.VCount = 0;
nds.lignerendu = FALSE;
if (Screen_Init(GFXCORE_DUMMY) != 0)
return -1;
#ifdef GDB_STUB
armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface);
armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface);
#else
armcpu_new(&NDS_ARM7,1);
armcpu_new(&NDS_ARM9,0);
#endif
if (SPU_Init(0, 0) != 0)
return -1;
#ifdef EXPERIMENTAL_WIFI
WIFI_Init(&wifiMac) ;
#endif
return 0;
}
static void armcpu_deinit(armcpu_t *armcpu)
{
if(armcpu->coproc[15])
{
free(armcpu->coproc[15]);
armcpu->coproc[15] = 0;
}
}
void NDS_DeInit(void) {
if(MMU.CART_ROM != MMU.UNUSED_RAM)
NDS_FreeROM();
armcpu_deinit(&NDS_ARM7);
armcpu_deinit(&NDS_ARM9);
nds.nextHBlank = 3168;
SPU_DeInit();
Screen_DeInit();
MMU_DeInit();
}
BOOL NDS_SetROM(u8 * rom, u32 mask)
{
MMU_setRom(rom, mask);
return TRUE;
}
NDS_header * NDS_getROMHeader(void)
{
NDS_header * header = malloc(sizeof(NDS_header));
memcpy(header->gameTile, MMU.CART_ROM, 12);
memcpy(header->gameCode, MMU.CART_ROM + 12, 4);
header->makerCode = T1ReadWord(MMU.CART_ROM, 16);
header->unitCode = MMU.CART_ROM[18];
header->deviceCode = MMU.CART_ROM[19];
header->cardSize = MMU.CART_ROM[20];
memcpy(header->cardInfo, MMU.CART_ROM + 21, 8);
header->flags = MMU.CART_ROM[29];
header->ARM9src = T1ReadLong(MMU.CART_ROM, 32);
header->ARM9exe = T1ReadLong(MMU.CART_ROM, 36);
header->ARM9cpy = T1ReadLong(MMU.CART_ROM, 40);
header->ARM9binSize = T1ReadLong(MMU.CART_ROM, 44);
header->ARM7src = T1ReadLong(MMU.CART_ROM, 48);
header->ARM7exe = T1ReadLong(MMU.CART_ROM, 52);
header->ARM7cpy = T1ReadLong(MMU.CART_ROM, 56);
header->ARM7binSize = T1ReadLong(MMU.CART_ROM, 60);
header->FNameTblOff = T1ReadLong(MMU.CART_ROM, 64);
header->FNameTblSize = T1ReadLong(MMU.CART_ROM, 68);
header->FATOff = T1ReadLong(MMU.CART_ROM, 72);
header->FATSize = T1ReadLong(MMU.CART_ROM, 76);
header->ARM9OverlayOff = T1ReadLong(MMU.CART_ROM, 80);
header->ARM9OverlaySize = T1ReadLong(MMU.CART_ROM, 84);
header->ARM7OverlayOff = T1ReadLong(MMU.CART_ROM, 88);
header->ARM7OverlaySize = T1ReadLong(MMU.CART_ROM, 92);
header->unknown2a = T1ReadLong(MMU.CART_ROM, 96);
header->unknown2b = T1ReadLong(MMU.CART_ROM, 100);
header->IconOff = T1ReadLong(MMU.CART_ROM, 104);
header->CRC16 = T1ReadWord(MMU.CART_ROM, 108);
header->ROMtimeout = T1ReadWord(MMU.CART_ROM, 110);
header->ARM9unk = T1ReadLong(MMU.CART_ROM, 112);
header->ARM7unk = T1ReadLong(MMU.CART_ROM, 116);
memcpy(header->unknown3c, MMU.CART_ROM + 120, 8);
header->ROMSize = T1ReadLong(MMU.CART_ROM, 128);
header->HeaderSize = T1ReadLong(MMU.CART_ROM, 132);
memcpy(header->unknown5, MMU.CART_ROM + 136, 56);
memcpy(header->logo, MMU.CART_ROM + 192, 156);
header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348);
header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350);
memcpy(header->reserved, MMU.CART_ROM + 352, 160);
return header;
//return (NDS_header *)MMU.CART_ROM;
}
void NDS_FreeROM(void)
{
if (MMU.CART_ROM != MMU.UNUSED_RAM)
free(MMU.CART_ROM);
MMU_unsetRom();
// if (MMU.bupmem.fp)
// fclose(MMU.bupmem.fp);
// MMU.bupmem.fp = NULL;
}
void NDS_Reset( void)
{
BOOL oldexecute=execute;
int i;
u32 src;
u32 dst;
NDS_header * header = NDS_getROMHeader();
if (!header) return ;
execute = FALSE;
MMU_clearMem();
src = header->ARM9src;
dst = header->ARM9cpy;
for(i = 0; i < (header->ARM9binSize>>2); ++i)
{
MMU_write32(0, dst, T1ReadLong(MMU.CART_ROM, src));
dst += 4;
src += 4;
}
src = header->ARM7src;
dst = header->ARM7cpy;
for(i = 0; i < (header->ARM7binSize>>2); ++i)
{
MMU_write32(1, dst, T1ReadLong(MMU.CART_ROM, src));
dst += 4;
src += 4;
}
armcpu_init(&NDS_ARM7, header->ARM7exe);
armcpu_init(&NDS_ARM9, header->ARM9exe);
nds.ARM9Cycle = 0;
nds.ARM7Cycle = 0;
nds.cycles = 0;
memset(nds.timerCycle, 0, sizeof(s32) * 2 * 4);
memset(nds.timerOver, 0, sizeof(BOOL) * 2 * 4);
nds.nextHBlank = 3168;
nds.VCount = 0;
nds.old = 0;
nds.diff = 0;
nds.lignerendu = FALSE;
nds.touchX = nds.touchY = 0;
MMU_write16(0, 0x04000130, 0x3FF);
MMU_write16(1, 0x04000130, 0x3FF);
MMU_write8(1, 0x04000136, 0x43);
/*
* Setup a copy of the firmware user settings in memory.
* (this is what the DS firmware would do).
*/
{
u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT];
int fw_index;
if ( copy_firmware_user_data( temp_buffer, MMU.fw.data)) {
for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) {
MMU_write8( 0, 0x027FFC80 + fw_index, temp_buffer[fw_index]);
}
}
}
// Copy the whole header to Main RAM 0x27FFE00 on startup.
// Reference: http://nocash.emubase.de/gbatek.htm#dscartridgeheader
for (i = 0; i < ((0x170+0x90)/4); i++)
{
MMU_write32 (0, 0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i]));
}
MainScreen.offset = 0;
SubScreen.offset = 192;
//MMU_write32(0, 0x02007FFC, 0xE92D4030);
//ARM7 BIOS IRQ HANDLER
MMU_write32(1, 0x00, 0xE25EF002);
MMU_write32(1, 0x04, 0xEAFFFFFE);
MMU_write32(1, 0x18, 0xEA000000);
MMU_write32(1, 0x20, 0xE92D500F);
MMU_write32(1, 0x24, 0xE3A00301);
MMU_write32(1, 0x28, 0xE28FE000);
MMU_write32(1, 0x2C, 0xE510F004);
MMU_write32(1, 0x30, 0xE8BD500F);
MMU_write32(1, 0x34, 0xE25EF004);
//ARM9 BIOS IRQ HANDLER
MMU_write32(0, 0xFFFF0018, 0xEA000000);
MMU_write32(0, 0xFFFF0020, 0xE92D500F);
MMU_write32(0, 0xFFFF0024, 0xEE190F11);
MMU_write32(0, 0xFFFF0028, 0xE1A00620);
MMU_write32(0, 0xFFFF002C, 0xE1A00600);
MMU_write32(0, 0xFFFF0030, 0xE2800C40);
MMU_write32(0, 0xFFFF0034, 0xE28FE000);
MMU_write32(0, 0xFFFF0038, 0xE510F004);
MMU_write32(0, 0xFFFF003C, 0xE8BD500F);
MMU_write32(0, 0xFFFF0040, 0xE25EF004);
MMU_write32(0, 0x0000004, 0xE3A0010E);
MMU_write32(0, 0x0000008, 0xE3A01020);
// MMU_write32(0, 0x000000C, 0xE1B02110);
MMU_write32(0, 0x000000C, 0xE1B02040);
MMU_write32(0, 0x0000010, 0xE3B02020);
// MMU_write32(0, 0x0000010, 0xE2100202);
free(header);
GPU_Reset(MainScreen.gpu, 0);
GPU_Reset(SubScreen.gpu, 1);
SPU_Reset();
execute = oldexecute;
}
static void dma_check(void)
{
if((MMU.DMAing[0][0])&&(MMU.DMACycle[0][0]<=nds.cycles))
{
T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
if((MMU.DMACrt[0][0])&(1<<30)) NDS_makeARM9Int(8);
MMU.DMAing[0][0] = FALSE;
}
if((MMU.DMAing[0][1])&&(MMU.DMACycle[0][1]<=nds.cycles))
{
T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
if((MMU.DMACrt[0][1])&(1<<30)) NDS_makeARM9Int(9);
MMU.DMAing[0][1] = FALSE;
}
if((MMU.DMAing[0][2])&&(MMU.DMACycle[0][2]<=nds.cycles))
{
T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
if((MMU.DMACrt[0][2])&(1<<30)) NDS_makeARM9Int(10);
MMU.DMAing[0][2] = FALSE;
}
if((MMU.DMAing[0][3])&&(MMU.DMACycle[0][3]<=nds.cycles))
{
T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
if((MMU.DMACrt[0][3])&(1<<30)) NDS_makeARM9Int(11);
MMU.DMAing[0][3] = FALSE;
}
if((MMU.DMAing[1][0])&&(MMU.DMACycle[1][0]<=nds.cycles))
{
T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*0), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
if((MMU.DMACrt[1][0])&(1<<30)) NDS_makeARM7Int(8);
MMU.DMAing[1][0] = FALSE;
}
if((MMU.DMAing[1][1])&&(MMU.DMACycle[1][1]<=nds.cycles))
{
T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*1), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
if((MMU.DMACrt[1][1])&(1<<30)) NDS_makeARM7Int(9);
MMU.DMAing[1][1] = FALSE;
}
if((MMU.DMAing[1][2])&&(MMU.DMACycle[1][2]<=nds.cycles))
{
T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*2), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
if((MMU.DMACrt[1][2])&(1<<30)) NDS_makeARM7Int(10);
MMU.DMAing[1][2] = FALSE;
}
if((MMU.DMAing[1][3])&&(MMU.DMACycle[1][3]<=nds.cycles))
{
T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*3), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
if((MMU.DMACrt[1][3])&(1<<30)) NDS_makeARM7Int(11);
MMU.DMAing[1][3] = FALSE;
}
if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0]))
{
#ifdef GDB_STUB
if ( armcpu_flagIrq( &NDS_ARM9))
#else
if ( armcpu_irqExeption(&NDS_ARM9))
#endif
{
nds.ARM9Cycle = nds.cycles;
}
}
if((MMU.reg_IF[1]&MMU.reg_IE[1]) && (MMU.reg_IME[1]))
{
#ifdef GDB_STUB
if ( armcpu_flagIrq( &NDS_ARM7))
#else
if ( armcpu_irqExeption(&NDS_ARM7))
#endif
{
nds.ARM7Cycle = nds.cycles;
}
}
}
static void timer_check(void)
{
int p, t;
for (p = 0; p < 2; p++)
{
for (t = 0; t < 4; t++)
{
nds.timerOver[p][t] = 0;
if(MMU.timerON[p][t])
{
if(MMU.timerRUN[p][t])
{
switch(MMU.timerMODE[p][t])
{
case 0xFFFF :
if(t > 0 && nds.timerOver[p][t - 1])
{
++(MMU.timer[p][t]);
nds.timerOver[p][t] = !MMU.timer[p][t];
if (nds.timerOver[p][t])
{
if (p == 0)
{
if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40)
NDS_makeARM9Int(3 + t);
}
else
{
if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40)
NDS_makeARM7Int(3 + t);
}
MMU.timer[p][t] = MMU.timerReload[p][t];
}
}
break;
default :
{
nds.diff = (nds.cycles >> MMU.timerMODE[p][t]) - (nds.timerCycle[p][t] >> MMU.timerMODE[p][t]);
nds.old = MMU.timer[p][t];
MMU.timer[p][t] += nds.diff;
nds.timerCycle[p][t] += nds.diff << MMU.timerMODE[p][t];
nds.timerOver[p][t] = nds.old >= MMU.timer[p][t];
if(nds.timerOver[p][t])
{
if (p == 0)
{
if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40)
NDS_makeARM9Int(3 + t);
}
else
{
if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40)
NDS_makeARM7Int(3 + t);
}
MMU.timer[p][t] = MMU.timerReload[p][t] + MMU.timer[p][t] - nds.old;
}
}
break;
}
}
else
{
MMU.timerRUN[p][t] = TRUE;
nds.timerCycle[p][t] = nds.cycles;
}
}
}
}
}
void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
{
int h;
for (h = 0; h < 2; h++)
{
s32 nb = nds.cycles + (h ? (99 * 12) : (256 * 12));
while (nb > nds.ARM9Cycle && !NDS_ARM9.waitIRQ)
nds.ARM9Cycle += armcpu_exec(&NDS_ARM9) << (cpu_clockdown_level_arm9);
if (NDS_ARM9.waitIRQ) nds.ARM9Cycle = nb;
while (nb > nds.ARM7Cycle && !NDS_ARM7.waitIRQ)
nds.ARM7Cycle += armcpu_exec(&NDS_ARM7) << (1 + (cpu_clockdown_level_arm7));
if (NDS_ARM7.waitIRQ) nds.ARM7Cycle = nb;
nds.cycles = (nds.ARM9Cycle<nds.ARM7Cycle)?nds.ARM9Cycle : nds.ARM7Cycle;
/* HBLANK */
if (h)
{
T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 2);
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 2);
NDS_ARM9HBlankInt();
NDS_ARM7HBlankInt();
if(nds.VCount<192)
{
if(MMU.DMAStartTime[0][0] == 2)
MMU_doDMA(0, 0);
if(MMU.DMAStartTime[0][1] == 2)
MMU_doDMA(0, 1);
if(MMU.DMAStartTime[0][2] == 2)
MMU_doDMA(0, 2);
if(MMU.DMAStartTime[0][3] == 2)
MMU_doDMA(0, 3);
}
}
else
{
/* HDISP */
u32 vmatch;
nds.nextHBlank += 4260;
++nds.VCount;
T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFD);
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFD);
if(MMU.DMAStartTime[0][0] == 3)
MMU_doDMA(0, 0);
if(MMU.DMAStartTime[0][1] == 3)
MMU_doDMA(0, 1);
if(MMU.DMAStartTime[0][2] == 3)
MMU_doDMA(0, 2);
if(MMU.DMAStartTime[0][3] == 3)
MMU_doDMA(0, 3);
// Main memory display
if(MMU.DMAStartTime[0][0] == 4)
{
MMU_doDMA(0, 0);
MMU.DMAStartTime[0][0] = 0;
}
if(MMU.DMAStartTime[0][1] == 4)
{
MMU_doDMA(0, 1);
MMU.DMAStartTime[0][1] = 0;
}
if(MMU.DMAStartTime[0][2] == 4)
{
MMU_doDMA(0, 2);
MMU.DMAStartTime[0][2] = 0;
}
if(MMU.DMAStartTime[0][3] == 4)
{
MMU_doDMA(0, 3);
MMU.DMAStartTime[0][3] = 0;
}
if(MMU.DMAStartTime[1][0] == 4)
{
MMU_doDMA(1, 0);
MMU.DMAStartTime[1][0] = 0;
}
if(MMU.DMAStartTime[1][1] == 4)
{
MMU_doDMA(1, 1);
MMU.DMAStartTime[0][1] = 0;
}
if(MMU.DMAStartTime[1][2] == 4)
{
MMU_doDMA(1, 2);
MMU.DMAStartTime[1][2] = 0;
}
if(MMU.DMAStartTime[1][3] == 4)
{
MMU_doDMA(1, 3);
MMU.DMAStartTime[1][3] = 0;
}
if(nds.VCount == 192)
{
/* VBLANK */
T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 1);
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
NDS_ARM9VBlankInt();
NDS_ARM7VBlankInt();
if(MMU.DMAStartTime[0][0] == 1)
MMU_doDMA(0, 0);
if(MMU.DMAStartTime[0][1] == 1)
MMU_doDMA(0, 1);
if(MMU.DMAStartTime[0][2] == 1)
MMU_doDMA(0, 2);
if(MMU.DMAStartTime[0][3] == 1)
MMU_doDMA(0, 3);
if(MMU.DMAStartTime[1][0] == 1)
MMU_doDMA(1, 0);
if(MMU.DMAStartTime[1][1] == 1)
MMU_doDMA(1, 1);
if(MMU.DMAStartTime[1][2] == 1)
MMU_doDMA(1, 2);
if(MMU.DMAStartTime[1][3] == 1)
MMU_doDMA(1, 3);
}
else if(nds.VCount == 263)
{
const int cycles_per_frame = (263 * (99 * 12 + 256 * 12));
/* VDISP */
nds.nextHBlank = 3168;
nds.VCount = 0;
T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFE);
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFE);
nds.cycles -= cycles_per_frame;
nds.ARM9Cycle -= cycles_per_frame;
nds.ARM7Cycle -= cycles_per_frame;
nb -= cycles_per_frame;
if(MMU.timerON[0][0])
nds.timerCycle[0][0] -= cycles_per_frame;
if(MMU.timerON[0][1])
nds.timerCycle[0][1] -= cycles_per_frame;
if(MMU.timerON[0][2])
nds.timerCycle[0][2] -= cycles_per_frame;
if(MMU.timerON[0][3])
nds.timerCycle[0][3] -= cycles_per_frame;
if(MMU.timerON[1][0])
nds.timerCycle[1][0] -= cycles_per_frame;
if(MMU.timerON[1][1])
nds.timerCycle[1][1] -= cycles_per_frame;
if(MMU.timerON[1][2])
nds.timerCycle[1][2] -= cycles_per_frame;
if(MMU.timerON[1][3])
nds.timerCycle[1][3] -= cycles_per_frame;
if(MMU.DMAing[0][0])
MMU.DMACycle[0][0] -= cycles_per_frame;
if(MMU.DMAing[0][1])
MMU.DMACycle[0][1] -= cycles_per_frame;
if(MMU.DMAing[0][2])
MMU.DMACycle[0][2] -= cycles_per_frame;
if(MMU.DMAing[0][3])
MMU.DMACycle[0][3] -= cycles_per_frame;
if(MMU.DMAing[1][0])
MMU.DMACycle[1][0] -= cycles_per_frame;
if(MMU.DMAing[1][1])
MMU.DMACycle[1][1] -= cycles_per_frame;
if(MMU.DMAing[1][2])
MMU.DMACycle[1][2] -= cycles_per_frame;
if(MMU.DMAing[1][3])
MMU.DMACycle[1][3] -= cycles_per_frame;
}
T1WriteWord(ARM9Mem.ARM9_REG, 6, nds.VCount);
T1WriteWord(MMU.ARM7_REG, 6, nds.VCount);
vmatch = T1ReadWord(ARM9Mem.ARM9_REG, 4);
if((nds.VCount==(vmatch>>8)|((vmatch<<1)&(1<<8))))
{
T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 4);
if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 32)
NDS_makeARM9Int(2);
}
else
T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFB);
vmatch = T1ReadWord(MMU.ARM7_REG, 4);
if((nds.VCount==(vmatch>>8)|((vmatch<<1)&(1<<8))))
{
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4);
if(T1ReadWord(MMU.ARM7_REG, 4) & 32)
NDS_makeARM7Int(2);
}
else
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFB);
timer_check();
dma_check();
}
}
}
void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
{
int v;
for (v = 0; v < 263; v++)
{
NDS_exec_hframe(cpu_clockdown_level_arm9, cpu_clockdown_level_arm7);
}
}

View File

@ -0,0 +1,255 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NDSSYSTEM_H
#define NDSSYSTEM_H
#include "armcpu.h"
#include "MMU.h"
#include "GPU.h"
#include "SPU_exports.h"
#include "mem.h"
//#include "wifi.h"
#ifdef __cplusplus
extern "C" {
#endif
extern volatile BOOL execute;
extern BOOL click;
/*
* The firmware language values
*/
#define NDS_FW_LANG_JAP 0
#define NDS_FW_LANG_ENG 1
#define NDS_FW_LANG_FRE 2
#define NDS_FW_LANG_GER 3
#define NDS_FW_LANG_ITA 4
#define NDS_FW_LANG_SPA 5
#define NDS_FW_LANG_CHI 6
#define NDS_FW_LANG_RES 7
//#define LOG_ARM9
//#define LOG_ARM7
typedef struct
{
char gameTile[12];
char gameCode[4];
u16 makerCode;
u8 unitCode;
u8 deviceCode;
u8 cardSize;
u8 cardInfo[8];
u8 flags;
u32 ARM9src;
u32 ARM9exe;
u32 ARM9cpy;
u32 ARM9binSize;
u32 ARM7src;
u32 ARM7exe;
u32 ARM7cpy;
u32 ARM7binSize;
u32 FNameTblOff;
u32 FNameTblSize;
u32 FATOff;
u32 FATSize;
u32 ARM9OverlayOff;
u32 ARM9OverlaySize;
u32 ARM7OverlayOff;
u32 ARM7OverlaySize;
u32 unknown2a;
u32 unknown2b;
u32 IconOff;
u16 CRC16;
u16 ROMtimeout;
u32 ARM9unk;
u32 ARM7unk;
u8 unknown3c[8];
u32 ROMSize;
u32 HeaderSize;
u8 unknown5[56];
u8 logo[156];
u16 logoCRC16;
u16 headerCRC16;
u8 reserved[160];
} NDS_header;
extern void debug();
typedef struct
{
s32 ARM9Cycle;
s32 ARM7Cycle;
s32 cycles;
s32 timerCycle[2][4];
BOOL timerOver[2][4];
s32 nextHBlank;
u32 VCount;
u32 old;
s32 diff;
BOOL lignerendu;
u16 touchX;
u16 touchY;
} NDSSystem;
/** /brief A touchscreen calibration point.
*/
struct NDS_fw_touchscreen_cal {
u16 adc_x;
u16 adc_y;
u8 screen_x;
u8 screen_y;
};
/** /brief The type of DS
*/
enum nds_fw_ds_type {
NDS_FW_DS_TYPE_FAT,
NDS_FW_DS_TYPE_LITE
};
#define MAX_FW_NICKNAME_LENGTH 10
#define MAX_FW_MESSAGE_LENGTH 26
struct NDS_fw_config_data {
enum nds_fw_ds_type ds_type;
u8 fav_colour;
u8 birth_month;
u8 birth_day;
u16 nickname[MAX_FW_NICKNAME_LENGTH];
u8 nickname_len;
u16 message[MAX_FW_MESSAGE_LENGTH];
u8 message_len;
u8 language;
/* touchscreen calibration */
struct NDS_fw_touchscreen_cal touch_cal[2];
};
extern NDSSystem nds;
#ifdef GDB_STUB
int NDS_Init( struct armcpu_memory_iface *arm9_mem_if,
struct armcpu_ctrl_iface **arm9_ctrl_iface,
struct armcpu_memory_iface *arm7_mem_if,
struct armcpu_ctrl_iface **arm7_ctrl_iface);
#else
int NDS_Init ( void);
#endif
void NDS_DeInit(void);
void
NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config);
BOOL NDS_SetROM(u8 * rom, u32 mask);
NDS_header * NDS_getROMHeader(void);
void NDS_setTouchPos(u16 x, u16 y);
void NDS_releasTouch(void);
int NDS_LoadROM(const char *filename, int bmtype, u32 bmsize,
const char *cflash_disk_image_file);
void NDS_FreeROM(void);
void NDS_Reset(void);
int NDS_ImportSave(const char *filename);
int NDS_WriteBMP(const char *filename);
int NDS_LoadFirmware(const char *filename);
int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings);
u32
NDS_exec(s32 nb, BOOL force);
static INLINE void NDS_ARM9HBlankInt(void)
{
if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0x10)
{
MMU.reg_IF[0] |= 2;// & (MMU.reg_IME[0] << 1);// (MMU.reg_IE[0] & (1<<1));
NDS_ARM9.wIRQ = TRUE;
}
}
static INLINE void NDS_ARM7HBlankInt(void)
{
if(T1ReadWord(MMU.ARM7_REG, 4) & 0x10)
{
MMU.reg_IF[1] |= 2;// & (MMU.reg_IME[1] << 1);// (MMU.reg_IE[1] & (1<<1));
NDS_ARM7.wIRQ = TRUE;
}
}
static INLINE void NDS_ARM9VBlankInt(void)
{
if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0x8)
{
MMU.reg_IF[0] |= 1;// & (MMU.reg_IME[0]);// (MMU.reg_IE[0] & 1);
NDS_ARM9.wIRQ = TRUE;
//execute = FALSE;
/*logcount++;*/
}
}
static INLINE void NDS_ARM7VBlankInt(void)
{
if(T1ReadWord(MMU.ARM7_REG, 4) & 0x8)
MMU.reg_IF[1] |= 1;// & (MMU.reg_IME[1]);// (MMU.reg_IE[1] & 1);
NDS_ARM7.wIRQ = TRUE;
//execute = FALSE;
}
static INLINE void NDS_swapScreen(void)
{
u16 tmp = MainScreen.offset;
MainScreen.offset = SubScreen.offset;
SubScreen.offset = tmp;
}
void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7);
void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,951 @@
/* Copyright (C) 2006 Theo Berkau
Ideas borrowed from Stephane Dallongeville's SCSP core
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <string.h>
#include "ARM9.h"
#include "MMU.h"
#include "SPU.h"
#include "mem.h"
#include "armcpu.h"
enum
{
FORMAT_PCM8 = 0,
FORMAT_PCM16 = 1,
FORMAT_ADPCM = 2,
FORMAT_PSG = 3
};
#define VOL_SHIFT 10
typedef struct
{
int id;
int status;
int format;
u8 *buf8; s16 *buf16;
double pos, inc;
int loopend, looppos;
int loop, length;
s32 adpcm;
int adpcm_pos, adpcm_index;
s32 adpcm_loop;
int adpcm_loop_pos, adpcm_loop_index;
int psg_duty;
int timer;
int volume;
int pan;
int shift;
int repeat, hold;
u32 addr;
s32 volumel;
s32 volumer;
s16 output;
} SChannel;
typedef struct
{
s32 *pmixbuf;
s16 *pclipingbuf;
u32 buflen;
SChannel ch[16];
} SPU_struct;
static SPU_struct spu = { 0, 0, 0 };
static SoundInterface_struct *SNDCore=NULL;
extern SoundInterface_struct *SNDCoreList[];
int SPU_ChangeSoundCore(int coreid, int buffersize)
{
int i;
SPU_DeInit();
// Allocate memory for sound buffer
spu.buflen = buffersize * 2; /* stereo */
spu.pmixbuf = malloc(spu.buflen * sizeof(s32));
if (!spu.pmixbuf)
{
SPU_DeInit();
return -1;
}
spu.pclipingbuf = malloc(spu.buflen * sizeof(s16));
if (!spu.pclipingbuf)
{
SPU_DeInit();
return -1;
}
// So which core do we want?
if (coreid == SNDCORE_DEFAULT)
coreid = 0; // Assume we want the first one
// Go through core list and find the id
for (i = 0; SNDCoreList[i] != NULL; i++)
{
if (SNDCoreList[i]->id == coreid)
{
// Set to current core
SNDCore = SNDCoreList[i];
break;
}
}
if (SNDCore == NULL)
{
SPU_DeInit();
return -1;
}
if (SNDCore->Init(spu.buflen) == -1)
{
// Since it failed, instead of it being fatal, we'll just use the dummy
// core instead
SNDCore = &SNDDummy;
}
return 0;
}
int SPU_Init(int coreid, int buffersize)
{
SPU_DeInit();
SPU_Reset();
return SPU_ChangeSoundCore(coreid, buffersize);
}
void SPU_Pause(int pause)
{
if(pause)
SNDCore->MuteAudio();
else
SNDCore->UnMuteAudio();
}
void SPU_SetVolume(int volume)
{
if (SNDCore)
SNDCore->SetVolume(volume);
}
void SPU_DeInit(void)
{
spu.buflen = 0;
if (spu.pmixbuf)
{
free(spu.pmixbuf);
spu.pmixbuf = 0;
}
if (spu.pclipingbuf)
{
free(spu.pclipingbuf);
spu.pclipingbuf = 0;
}
if (SNDCore)
{
SNDCore->DeInit();
}
SNDCore = &SNDDummy;
}
static const short g_adpcm_index[16] = { -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, 4, 4, 6, 6, 8, 8 };
static const int g_adpcm_mult[89] =
{
0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, 0x0011,
0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, 0x0029, 0x002D,
0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076,
0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133,
0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C,
0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812,
0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE,
0x1706, 0x1954, 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B,
0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF,
};
static const s16 g_psg_duty[8][8] = {
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
{ -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
{ -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF },
};
static void reset_channel(SChannel *ch, int id)
{
ch->status = 0;
ch->id = id;
}
void SPU_Reset(void)
{
int i;
for (i = 0;i < 16; i++)
reset_channel(&spu.ch[i], i);
for (i = 0x400; i < 0x51D; i++)
T1WriteByte(MMU.ARM7_REG, i, 0);
}
void SPU_KeyOn(int channel)
{
}
static INLINE void adjust_channel_timer(SChannel *ch)
{
ch->inc = (((double)33512000) / (44100 * 2)) / (double)(0x10000 - ch->timer);
}
static int check_valid(u32 addr, u32 size)
{
u32 t1, t2;
if(size > MMU.MMU_MASK[1][(addr >> 20) & 0xff]) return 0;
t1 = addr;
t2 = (addr + size);
t1 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff];
t2 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff];
if(t2 < t1) return 0;
return 1;
}
static void start_channel(SChannel *ch)
{
switch(ch->format)
{
case FORMAT_PCM8:
{
u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
u32 size = ((ch->length + ch->loop) << 2);
if((p != NULL) && check_valid(ch->addr, size))
{
ch->buf8 = p + ofs;
ch->looppos = ch->loop << 2;
ch->loopend = size;
ch->pos = 0;
ch->status = 1;
}
}
break;
case FORMAT_PCM16:
{
u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
u32 size = ((ch->length + ch->loop) << 1);
if((p != NULL) && check_valid(ch->addr, size << 1))
{
ch->buf16 = (s16 *)(p + ofs - (ofs & 1));
ch->looppos = ch->loop << 1;
ch->loopend = size;
ch->pos = 0;
ch->status = 1;
}
}
break;
case FORMAT_ADPCM:
{
u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
u32 size = ((ch->length + ch->loop) << 3);
if((p != NULL) && check_valid(ch->addr, size >> 1))
{
ch->buf8 = p + ofs;
#ifdef WORDS_BIGENDIAN
ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3;
#else
ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3;
#endif
ch->adpcm_index = (ch->buf8[2] & 0x7F);
ch->adpcm_pos = 8;
ch->pos = 9;
ch->looppos = ch->loop << 3;
ch->loopend = size;
ch->adpcm_loop_index = -1;
ch->status = 1;
}
}
break;
case FORMAT_PSG:
ch->status = 1;
if(ch->id < 14)
{
ch->pos = 0;
}
else
{
ch->pos = 0x7FFF;
}
break;
}
}
static void stop_channel(SChannel *ch)
{
u32 addr = 0x400 + (ch->id << 4) + 3;
ch->status = 0;
T1WriteByte(MMU.ARM7_REG, addr, (u8)(T1ReadByte(MMU.ARM7_REG, addr) & ~0x80));
}
static void set_channel_volume(SChannel *ch)
{
s32 vol1 = (T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F) * ch->volume;
s32 vol2;
vol2 = vol1 * ch->pan;
vol1 = vol1 * (127-ch->pan);
ch->volumel = vol1 >> (21 - VOL_SHIFT + ch->shift);
ch->volumer = vol2 >> (21 - VOL_SHIFT + ch->shift);
}
void SPU_WriteByte(u32 addr, u8 x)
{
addr &= 0x00000FFF;
T1WriteByte(MMU.ARM7_REG, addr, x);
if(addr < 0x500)
{
SChannel *ch;
switch(addr & 0x0F)
{
case 0x0:
ch = spu.ch + (addr >> 4 & 0xF);
ch->volume = (x & 0x7F);
set_channel_volume(ch);
break;
case 0x1:
ch = spu.ch + (addr >> 4 & 0xF);
ch->shift = (x & 0x03);
ch->hold = (x >> 7 & 0x01);
set_channel_volume(ch);
break;
case 0x2:
ch = spu.ch + (addr >> 4 & 0xF);
ch->pan = (x & 0x7F);
set_channel_volume(ch);
break;
case 0x3:
ch = spu.ch + (addr >> 4 & 0xF);
ch->psg_duty = (x & 0x07);
ch->repeat = (x >> 3 & 0x03);
ch->format = (x >> 5 & 0x03);
if(x & 0x80) start_channel(ch); else stop_channel(ch);
break;
#if !DISABLE_XSF_TESTS
case 0x04:
case 0x05:
case 0x06:
case 0x07:
ch = spu.ch + (addr >> 4 & 0xF);
ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF);
break;
case 0x08:
case 0x09:
ch = spu.ch + (addr >> 4 & 0xF);
ch->timer = T1ReadWord(MMU.ARM7_REG, addr & ~1);
adjust_channel_timer(ch);
break;
case 0x0a:
case 0x0b:
ch = spu.ch + (addr >> 4 & 0xF);
ch->loop = T1ReadWord(MMU.ARM7_REG, addr & ~1);
break;
case 0x0c:
case 0x0e:
case 0x0d:
case 0x0f:
ch = spu.ch + (addr >> 4 & 0xF);
ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF);
break;
#endif
}
}
}
void SPU_WriteWord(u32 addr, u16 x)
{
addr &= 0x00000FFF;
T1WriteWord(MMU.ARM7_REG, addr, x);
if(addr < 0x500)
{
SChannel *ch;
switch(addr & 0x00F)
{
case 0x0:
ch = spu.ch + (addr >> 4 & 0xF);
ch->volume = (x & 0x007F);
ch->shift = (x >> 8 & 0x0003);
ch->hold = (x >> 15 & 0x0001);
set_channel_volume(ch);
break;
case 0x2:
ch = spu.ch + (addr >> 4 & 0xF);
ch->pan = (x & 0x007F);
ch->psg_duty = (x >> 8 & 0x0007);
ch->repeat = (x >> 11 & 0x0003);
ch->format = (x >> 13 & 0x0003);
set_channel_volume(ch);
if(x & 0x8000) start_channel(ch); else stop_channel(ch);
break;
case 0x08:
ch = spu.ch + (addr >> 4 & 0xF);
ch->timer = x;
adjust_channel_timer(ch);
break;
case 0x0a:
ch = spu.ch + (addr >> 4 & 0xF);
ch->loop = x;
break;
#if !DISABLE_XSF_TESTS
case 0x04:
case 0x06:
ch = spu.ch + (addr >> 4 & 0xF);
ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF);
break;
case 0x0c:
case 0x0e:
ch = spu.ch + (addr >> 4 & 0xF);
ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF);
break;
#endif
}
}
}
void SPU_WriteLong(u32 addr, u32 x)
{
addr &= 0x00000FFF;
T1WriteLong(MMU.ARM7_REG, addr, x);
if(addr < 0x500)
{
SChannel *ch;
switch(addr & 0x00F)
{
case 0x0:
ch = spu.ch + (addr >> 4 & 0xF);
ch->volume = (x & 0x7F);
ch->shift = (x >> 8 & 0x00000003);
ch->hold = (x >> 15 & 0x00000001);
ch->pan = (x >> 16 & 0x0000007F);
ch->psg_duty = (x >> 24 & 0x00000007);
ch->repeat = (x >> 27 & 0x00000003);
ch->format = (x >> 29 & 0x00000003);
set_channel_volume(ch);
if(x & 0x80000000) start_channel(ch); else stop_channel(ch);
break;
case 0x04:
ch = spu.ch + (addr >> 4 & 0xF);
ch->addr = (x & 0x07FFFFFF);
break;
case 0x08:
ch = spu.ch + (addr >> 4 & 0xF);
ch->timer = (x & 0x0000FFFF);
ch->loop = (x >> 16 & 0x0000FFFF);
adjust_channel_timer(ch);
break;
case 0x0C:
ch = spu.ch + (addr >> 4 & 0xF);
ch->length = (x & 0x003FFFFF);
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////
u32 SPU_ReadLong(u32 addr)
{
addr &= 0xFFF;
return T1ReadLong(MMU.ARM7_REG, addr);
}
static INLINE s32 clipping(s32 x, s32 min, s32 max) {
#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
if (x < min)
{
return (min);
}
else if (x > max)
{
return (max);
}
return (x);
#else
return x ^ ((-(x < min)) & (x ^ min)) ^ ((-(x > max)) & (x ^ max));
#endif
}
extern unsigned long dwChannelMute;
static void decode_pcm8(SChannel *ch, s32 *out, int length)
{
int oi;
double pos, inc, len;
if (!ch->buf8) return;
pos = ch->pos; inc = ch->inc; len = ch->loopend;
for(oi = 0; oi < length; oi++)
{
ch->output = ((s16)(s8)ch->buf8[(int)pos]) << 8;
if (dwChannelMute & (1 << ch->id))
{
out++;
out++;
}
else
{
*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
}
pos += inc;
if(pos >= len)
{
switch(ch->repeat)
{
#if !DISABLE_XSF_TESTS
case 0:
#endif
case 1:
pos += ch->looppos - len;
break;
default:
stop_channel(ch);
oi = length;
break;
}
}
}
ch->pos = pos;
return;
}
static void decode_pcm16(SChannel *ch, s32 *out, int length)
{
int oi;
double pos, inc, len;
if (!ch->buf16) return;
pos = ch->pos; inc = ch->inc; len = ch->loopend;
for(oi = 0; oi < length; oi++)
{
#ifdef WORDS_BIGENDIAN
ch->output = (s16)T1ReadWord((u8 *)ch->buf16, pos << 1);
#else
ch->output = (s16)ch->buf16[(int)pos];
#endif
if (dwChannelMute & (1 << ch->id))
{
out++;
out++;
}
else
{
*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
}
pos += inc;
if(pos >= len)
{
switch(ch->repeat)
{
#if !DISABLE_XSF_TESTS
case 0:
#endif
case 1:
pos += ch->looppos - len;
break;
default:
stop_channel(ch);
oi = length;
break;
}
}
}
ch->pos = pos;
}
static INLINE void decode_adpcmone_P4(SChannel *ch, int m)
{
int i, ci0;
u8 *p;
s32 s;
int N;
i = ch->adpcm_pos;
p = (ch->buf8 + (i >> 1));
ci0 = ch->adpcm_index;
s = ch->adpcm;
if (ch->adpcm_loop_index < 0 && m >= ch->looppos)
{
ch->adpcm_loop_index = ci0;
ch->adpcm_loop = s;
ch->adpcm_loop_pos = i;
}
if(i++ & 1)
{
s32 x1, d1;
x1 = ((*(p++) >> 3) & 0x1F | 1);
d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7);
ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88);
#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
if(x1 & 0x10) d1 = -d1;
#else
d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
#endif
s = clipping((s + d1), (-32768 << 3), (32767 << 3));
}
N = (((m & ~1) - (i & ~1)) >> 1);
for(i = 0; i < N; i++)
{
s32 x0, d0;
s32 x1, d1;
int ci1;
x0 = ((*p << 1) & 0x1F | 1);
x1 = ((*p >> 3) & 0x1F | 1);
ci1 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88);
d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7);
ci0 = clipping((ci1 + g_adpcm_index[x1 & 0xE]), 0, 88);
d1 = ((x1 & 0xF) * g_adpcm_mult[ci1] & ~7);
#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
if(x0 & 0x10) d0 = -d0;
if(x1 & 0x10) d1 = -d1;
#else
d0 -= (d0 + d0) & (-(((x0 >> 4) & 1)));
d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
#endif
s = clipping((s + d0), (-32768 << 3), (32767 << 3));
s = clipping((s + d1), (-32768 << 3), (32767 << 3));
p++;
}
if(m & 1)
{
s32 x0, d0;
x0 = ((*p << 1) & 0x1F | 1);
d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7);
ci0 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88);
#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
if(x0 & 0x10) d0 = -d0;
#else
d0 -= (d0 + d0) & (-(((x0 >> 4) & 1)));
#endif
s = clipping((s + d0), (-32768 << 3), (32767 << 3));
}
ch->output = (s16)(s >> 3);
ch->adpcm = s;
ch->adpcm_index = ci0;
ch->adpcm_pos = m;
}
static INLINE void decode_adpcmone_XX(SChannel *ch, int m)
{
int i, ci0;
u8 *p;
s32 s;
i = ch->adpcm_pos;
p = (ch->buf8 + (i >> 1));
ci0 = ch->adpcm_index;
s = ch->adpcm;
if (ch->adpcm_loop_index < 0 && m >= ch->looppos)
{
ch->adpcm_loop_index = ci0;
ch->adpcm_loop = s;
ch->adpcm_loop_pos = i;
}
while (i < m)
{
s32 x1, d1;
x1 = ((s32)*p) >> ((i & 1) << 2) & 0xf;
x1 = x1 + x1 + 1;
d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7);
ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88);
#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
if(x1 & 0x10) d1 = -d1;
#else
d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
#endif
s = clipping((s + d1), (-32768 << 3), (32767 << 3));
p += (i & 1);
i++;
}
ch->output = (s16)(s >> 3);
ch->adpcm = s;
ch->adpcm_index = ci0;
ch->adpcm_pos = m;
}
#define decode_adpcmone decode_adpcmone_P4
static void decode_adpcm(SChannel *ch, s32 *out, int length)
{
int oi;
double pos, inc, len;
if (!ch->buf8) return;
pos = ch->pos; inc = ch->inc; len = ch->loopend;
for(oi = 0; oi < length; oi++)
{
int m = (int)pos;
int i = ch->adpcm_pos;
if(i < m)
decode_adpcmone(ch, m);
if (dwChannelMute & (1 << ch->id))
{
out++;
out++;
}
else
{
*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
}
pos += inc;
if(pos >= len)
{
switch(ch->repeat)
{
case 1:
if (ch->adpcm_loop_index >= 0)
{
pos += ch->looppos - len;
ch->adpcm_pos = ch->adpcm_loop_pos;
ch->adpcm_index = ch->adpcm_loop_index;
ch->adpcm = ch->adpcm_loop;
break;
}
#if !DISABLE_XSF_TESTS
case 0:
pos = 9 - len;
#ifdef WORDS_BIGENDIAN
ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3;
#else
ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3;
#endif
ch->adpcm_index = (ch->buf8[2] & 0x7F);
ch->adpcm_pos = 8;
break;
#endif
default:
stop_channel(ch);
oi = length;
break;
}
}
}
ch->pos = pos;
}
static void decode_psg(SChannel *ch, s32 *out, int length)
{
int oi;
if(ch->id < 14)
{
// NOTE: square wave.
double pos, inc, len;
pos = ch->pos; inc = ch->inc; len = ch->length;
for(oi = 0; oi < length; oi++)
{
ch->output = (s16)g_psg_duty[ch->psg_duty][(int)pos & 0x00000007];
if (dwChannelMute & (1 << ch->id))
{
out++;
out++;
}
else
{
*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
}
pos += inc;
}
ch->pos = pos;
}
else
{
// NOTE: noise.
u16 X;
X = (u16)ch->pos;
for(oi = 0; oi < length; oi++)
{
if(X & 1)
{
X >>= 1;
X ^= 0x6000;
ch->output = -0x8000;
}
else
{
X >>= 1;
ch->output = +0x7FFF;
}
}
if (dwChannelMute & (1 << ch->id))
{
out++;
out++;
}
else
{
*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
}
ch->pos = X;
}
}
void SPU_EmulateSamples(u32 numsamples)
{
u32 sizesmp = numsamples;
u32 sizebyte = sizesmp << 2;
if (sizebyte > spu.buflen * sizeof(s16)) sizebyte = spu.buflen * sizeof(s16);
sizesmp = sizebyte >> 2;
sizebyte = sizesmp << 2;
if (sizesmp > 0)
{
unsigned i;
SChannel *ch = spu.ch;
memset(spu.pmixbuf, 0, spu.buflen * sizeof(s32));
for (i = 0; i < 16; i++)
{
if (ch->status)
{
switch (ch->format)
{
case 0:
decode_pcm8(ch, spu.pmixbuf, sizesmp);
break;
case 1:
decode_pcm16(ch, spu.pmixbuf, sizesmp);
break;
case 2:
decode_adpcm(ch, spu.pmixbuf, sizesmp);
break;
case 3:
decode_psg(ch, spu.pmixbuf, sizesmp);
break;
}
}
ch++;
}
for (i = 0; i < sizesmp * 2; i++)
spu.pclipingbuf[i] = (s16)clipping(spu.pmixbuf[i], -0x8000, 0x7fff);
SNDCore->UpdateAudio(spu.pclipingbuf, sizesmp);
}
}
void SPU_Emulate(void)
{
SPU_EmulateSamples(SNDCore->GetAudioSpace());
}
//////////////////////////////////////////////////////////////////////////////
// Dummy Sound Interface
//////////////////////////////////////////////////////////////////////////////
static int SNDDummyInit(int buffersize)
{
return 0;
}
//////////////////////////////////////////////////////////////////////////////
static void SNDDummyDeInit()
{
}
//////////////////////////////////////////////////////////////////////////////
static void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples)
{
}
//////////////////////////////////////////////////////////////////////////////
static u32 SNDDummyGetAudioSpace()
{
return 735;
}
//////////////////////////////////////////////////////////////////////////////
static void SNDDummyMuteAudio()
{
}
//////////////////////////////////////////////////////////////////////////////
static void SNDDummyUnMuteAudio()
{
}
//////////////////////////////////////////////////////////////////////////////
static void SNDDummySetVolume(int volume)
{
}
//////////////////////////////////////////////////////////////////////////////
SoundInterface_struct SNDDummy =
{
SNDCORE_DUMMY,
"Dummy Sound Interface",
SNDDummyInit,
SNDDummyDeInit,
SNDDummyUpdateAudio,
SNDDummyGetAudioSpace,
SNDDummyMuteAudio,
SNDDummyUnMuteAudio,
SNDDummySetVolume
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
/* SPU.h
Copyright 2006 Theo Berkau
Copyright (C) 2006-2009 DeSmuME team
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SPU_H
#define SPU_H
#include <string>
#include "types.h"
#define FORCEINLINE __forceinline
#define SNDCORE_DEFAULT -1
#define SNDCORE_DUMMY 0
#define CHANSTAT_STOPPED 0
#define CHANSTAT_PLAY 1
enum SPUInterpolationMode
{
SPUInterpolation_None = 0,
SPUInterpolation_Linear = 1,
SPUInterpolation_Cosine = 2
};
struct SoundInterface_struct
{
int id;
const char *Name;
int (*Init)(int buffersize);
void (*DeInit)();
void (*UpdateAudio)(s16 *buffer, u32 num_samples);
u32 (*GetAudioSpace)();
void (*MuteAudio)();
void (*UnMuteAudio)();
void (*SetVolume)(int volume);
};
extern SoundInterface_struct SNDDummy;
extern SoundInterface_struct SNDFile;
extern int SPU_currentCoreNum;
struct channel_struct
{
channel_struct()
{}
u32 num;
u8 vol;
u8 datashift;
u8 hold;
u8 pan;
u8 waveduty;
u8 repeat;
u8 format;
u8 status;
u32 addr;
u16 timer;
u16 loopstart;
u32 length;
u32 totlength;
double double_totlength_shifted;
union {
s8 *buf8;
s16 *buf16;
};
double sampcnt;
double sampinc;
// ADPCM specific
u32 lastsampcnt;
s16 pcm16b, pcm16b_last;
s16 loop_pcm16b;
int index;
int loop_index;
u16 x;
s16 psgnoise_last;
} ;
class SPU_struct
{
public:
SPU_struct(int buffersize);
u32 bufpos;
u32 buflength;
s32 *sndbuf;
s16 *outbuf;
u32 bufsize;
channel_struct channels[16];
void reset();
~SPU_struct();
void KeyOn(int channel);
void WriteByte(u32 addr, u8 val);
void WriteWord(u32 addr, u16 val);
void WriteLong(u32 addr, u32 val);
//kills all channels but leaves SPU otherwise running normally
void ShutUp();
};
SoundInterface_struct *SPU_SoundCore();
void SPU_Pause(int pause);
void SPU_SetVolume(int volume);
void SPU_KeyOn(int channel);
void SPU_Emulate_core(void);
void SPU_Emulate_user(bool mix = true);
extern SPU_struct *SPU_core, *SPU_user;
extern int spu_core_samples;
class WavWriter
{
public:
WavWriter();
bool open(const std::string & fname);
void close();
void update(void* soundData, int numSamples);
bool isRecording() const;
private:
FILE *spufp;
};
void WAV_End();
bool WAV_Begin(const char* fname);
bool WAV_IsRecording();
void WAV_WavSoundUpdate(void* soundData, int numSamples);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef ARMINSTRUCTION_H
#define ARMINSTRUCTION_H
#include "types.h"
#include "armcpu.h"
extern u32 (FASTCALL* arm_instructions_set[4096])(armcpu_t * cpu);
#endif

View File

@ -0,0 +1,579 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "arm_instructions.h"
#include "thumb_instructions.h"
#include "cp15.h"
#include "bios.h"
#include <stdlib.h>
#include <stdio.h>
const unsigned char arm_cond_table[16*16] = {
/* N=0, Z=0, C=0, V=0 */
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
/* N=0, Z=0, C=0, V=1 */
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=0, Z=0, C=1, V=0 */
0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
/* N=0, Z=0, C=1, V=1 */
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=0, Z=1, C=0, V=0 */
0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
/* N=0, Z=1, C=0, V=1 */
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=0, Z=1, C=1, V=0 */
0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
/* N=0, Z=1, C=1, V=1 */
0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=0, C=0, V=0 */
0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=0, C=0, V=1 */
0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00,
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
/* N=1, Z=0, C=1, V=0 */
0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF,
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=0, C=1, V=1 */
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00,
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
/* N=1, Z=1, C=0, V=0 */
0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=1, C=0, V=1 */
0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00,
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
/* N=1, Z=1, C=1, V=0 */
0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=1, C=1, V=1 */
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
};
armcpu_t NDS_ARM7;
armcpu_t NDS_ARM9;
#define SWAP(a, b, c) do \
{ \
c=a; \
a=b; \
b=c; \
} \
while(0)
#ifdef GDB_STUB
#define STALLED_CYCLE_COUNT 10
static void
stall_cpu( void *instance) {
armcpu_t *armcpu = (armcpu_t *)instance;
armcpu->stalled = 1;
}
static void
unstall_cpu( void *instance) {
armcpu_t *armcpu = (armcpu_t *)instance;
armcpu->stalled = 0;
}
static void
install_post_exec_fn( void *instance,
void (*ex_fn)( void *, u32 adr, int thumb),
void *fn_data) {
armcpu_t *armcpu = (armcpu_t *)instance;
armcpu->post_ex_fn = ex_fn;
armcpu->post_ex_fn_data = fn_data;
}
static void
remove_post_exec_fn( void *instance) {
armcpu_t *armcpu = (armcpu_t *)instance;
armcpu->post_ex_fn = NULL;
}
#endif
static u32
read_cpu_reg( void *instance, u32 reg_num) {
armcpu_t *armcpu = (armcpu_t *)instance;
u32 reg_value = 0;
if ( reg_num <= 14) {
reg_value = armcpu->R[reg_num];
}
else if ( reg_num == 15) {
reg_value = armcpu->next_instruction;
}
else if ( reg_num == 16) {
/* CPSR */
reg_value = armcpu->CPSR.val;
}
return reg_value;
}
static void
set_cpu_reg( void *instance, u32 reg_num, u32 value) {
armcpu_t *armcpu = (armcpu_t *)instance;
if ( reg_num <= 14) {
armcpu->R[reg_num] = value;
}
else if ( reg_num == 15) {
armcpu->next_instruction = value;
}
else if ( reg_num == 16) {
/* FIXME: setting the CPSR */
}
}
#ifdef GDB_STUB
int armcpu_new( armcpu_t *armcpu, u32 id,
struct armcpu_memory_iface *mem_if,
struct armcpu_ctrl_iface **ctrl_iface_ret)
#else
int armcpu_new( armcpu_t *armcpu, u32 id)
#endif
{
armcpu->proc_ID = id;
if(id==0)
armcpu->swi_tab = ARM9_swi_tab;
else
armcpu->swi_tab = ARM7_swi_tab;
#ifdef GDB_STUB
armcpu->mem_if = mem_if;
/* populate the control interface */
armcpu->ctrl_iface.stall = stall_cpu;
armcpu->ctrl_iface.unstall = unstall_cpu;
armcpu->ctrl_iface.read_reg = read_cpu_reg;
armcpu->ctrl_iface.set_reg = set_cpu_reg;
armcpu->ctrl_iface.install_post_ex_fn = install_post_exec_fn;
armcpu->ctrl_iface.remove_post_ex_fn = remove_post_exec_fn;
armcpu->ctrl_iface.data = armcpu;
*ctrl_iface_ret = &armcpu->ctrl_iface;
armcpu->stalled = 0;
armcpu->post_ex_fn = NULL;
#endif
armcpu_init(armcpu, 0);
return 0;
}
void armcpu_init(armcpu_t *armcpu, u32 adr)
{
u32 i;
armcpu->LDTBit = (armcpu->proc_ID==0); //Si ARM9 utiliser le syte v5 pour le load
armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0);
armcpu->waitIRQ = FALSE;
armcpu->wirq = FALSE;
#ifdef GDB_STUB
armcpu->irq_flag = 0;
#endif
if(armcpu->coproc[15]) free(armcpu->coproc[15]);
for(i = 0; i < 15; ++i)
{
armcpu->R[i] = 0;
armcpu->coproc[i] = NULL;
}
armcpu->CPSR.val = armcpu->SPSR.val = SYS;
armcpu->R13_usr = armcpu->R14_usr = 0;
armcpu->R13_svc = armcpu->R14_svc = 0;
armcpu->R13_abt = armcpu->R14_abt = 0;
armcpu->R13_und = armcpu->R14_und = 0;
armcpu->R13_irq = armcpu->R14_irq = 0;
armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0;
armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0;
#ifdef GDB_STUB
armcpu->instruct_adr = adr;
armcpu->R[15] = adr + 8;
#else
armcpu->R[15] = adr;
#endif
armcpu->next_instruction = adr;
armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu);
#ifndef GDB_STUB
armcpu_prefetch(armcpu);
#endif
}
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
{
u32 oldmode = armcpu->CPSR.bits.mode;
switch(oldmode)
{
case USR :
case SYS :
armcpu->R13_usr = armcpu->R[13];
armcpu->R14_usr = armcpu->R[14];
break;
case FIQ :
{
u32 tmp;
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
armcpu->R13_fiq = armcpu->R[13];
armcpu->R14_fiq = armcpu->R[14];
armcpu->SPSR_fiq = armcpu->SPSR;
break;
}
case IRQ :
armcpu->R13_irq = armcpu->R[13];
armcpu->R14_irq = armcpu->R[14];
armcpu->SPSR_irq = armcpu->SPSR;
break;
case SVC :
armcpu->R13_svc = armcpu->R[13];
armcpu->R14_svc = armcpu->R[14];
armcpu->SPSR_svc = armcpu->SPSR;
break;
case ABT :
armcpu->R13_abt = armcpu->R[13];
armcpu->R14_abt = armcpu->R[14];
armcpu->SPSR_abt = armcpu->SPSR;
break;
case UND :
armcpu->R13_und = armcpu->R[13];
armcpu->R14_und = armcpu->R[14];
armcpu->SPSR_und = armcpu->SPSR;
break;
default :
break;
}
switch(mode)
{
case USR :
case SYS :
armcpu->R[13] = armcpu->R13_usr;
armcpu->R[14] = armcpu->R14_usr;
//SPSR = CPSR;
break;
case FIQ :
{
u32 tmp;
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
armcpu->R[13] = armcpu->R13_fiq;
armcpu->R[14] = armcpu->R14_fiq;
armcpu->SPSR = armcpu->SPSR_fiq;
break;
}
case IRQ :
armcpu->R[13] = armcpu->R13_irq;
armcpu->R[14] = armcpu->R14_irq;
armcpu->SPSR = armcpu->SPSR_irq;
break;
case SVC :
armcpu->R[13] = armcpu->R13_svc;
armcpu->R[14] = armcpu->R14_svc;
armcpu->SPSR = armcpu->SPSR_svc;
break;
case ABT :
armcpu->R[13] = armcpu->R13_abt;
armcpu->R[14] = armcpu->R14_abt;
armcpu->SPSR = armcpu->SPSR_abt;
break;
case UND :
armcpu->R[13] = armcpu->R13_und;
armcpu->R[14] = armcpu->R14_und;
armcpu->SPSR = armcpu->SPSR_und;
break;
default :
break;
}
armcpu->CPSR.bits.mode = mode & 0x1F;
return oldmode;
}
static u32
armcpu_prefetch(armcpu_t *armcpu)
{
u32 temp_instruction;
if(armcpu->CPSR.bits.T == 0)
{
#ifdef GDB_STUB
temp_instruction =
armcpu->mem_if->prefetch32( armcpu->mem_if->data,
armcpu->next_instruction);
if ( !armcpu->stalled) {
armcpu->instruction = temp_instruction;
armcpu->instruct_adr = armcpu->next_instruction;
armcpu->next_instruction += 4;
armcpu->R[15] = armcpu->next_instruction + 4;
}
#else
armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
armcpu->instruct_adr = armcpu->next_instruction;
armcpu->next_instruction += 4;
armcpu->R[15] = armcpu->next_instruction + 4;
#endif
return MMU.MMU_WAIT32[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF];
}
#ifdef GDB_STUB
temp_instruction =
armcpu->mem_if->prefetch16( armcpu->mem_if->data,
armcpu->next_instruction);
if ( !armcpu->stalled) {
armcpu->instruction = temp_instruction;
armcpu->instruct_adr = armcpu->next_instruction;
armcpu->next_instruction = armcpu->next_instruction + 2;
armcpu->R[15] = armcpu->next_instruction + 2;
}
#else
armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
armcpu->instruct_adr = armcpu->next_instruction;
armcpu->next_instruction += 2;
armcpu->R[15] = armcpu->next_instruction + 2;
#endif
return MMU.MMU_WAIT16[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF];
}
static BOOL FASTCALL test_EQ(Status_Reg CPSR) { return ( CPSR.bits.Z); }
static BOOL FASTCALL test_NE(Status_Reg CPSR) { return (!CPSR.bits.Z); }
static BOOL FASTCALL test_CS(Status_Reg CPSR) { return ( CPSR.bits.C); }
static BOOL FASTCALL test_CC(Status_Reg CPSR) { return (!CPSR.bits.C); }
static BOOL FASTCALL test_MI(Status_Reg CPSR) { return ( CPSR.bits.N); }
static BOOL FASTCALL test_PL(Status_Reg CPSR) { return (!CPSR.bits.N); }
static BOOL FASTCALL test_VS(Status_Reg CPSR) { return ( CPSR.bits.V); }
static BOOL FASTCALL test_VC(Status_Reg CPSR) { return (!CPSR.bits.V); }
static BOOL FASTCALL test_HI(Status_Reg CPSR) { return (CPSR.bits.C) && (!CPSR.bits.Z); }
static BOOL FASTCALL test_LS(Status_Reg CPSR) { return (CPSR.bits.Z) || (!CPSR.bits.C); }
static BOOL FASTCALL test_GE(Status_Reg CPSR) { return (CPSR.bits.N==CPSR.bits.V); }
static BOOL FASTCALL test_LT(Status_Reg CPSR) { return (CPSR.bits.N!=CPSR.bits.V); }
static BOOL FASTCALL test_GT(Status_Reg CPSR) { return (!CPSR.bits.Z) && (CPSR.bits.N==CPSR.bits.V); }
static BOOL FASTCALL test_LE(Status_Reg CPSR) { return ( CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V); }
static BOOL FASTCALL test_AL(Status_Reg CPSR) { return 1; }
static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= {
test_EQ , test_NE ,
test_CS , test_CC ,
test_MI , test_PL ,
test_VS , test_VC ,
test_HI , test_LS ,
test_GE , test_LT ,
test_GT , test_LE ,
test_AL
};
#define TEST_COND2(cond, CPSR) \
(cond<15&&test_conditions[cond](CPSR))
BOOL armcpu_irqExeption(armcpu_t *armcpu)
{
Status_Reg tmp;
if(armcpu->CPSR.bits.I) return FALSE;
#ifdef GDB_STUB
armcpu->irq_flag = 0;
#endif
tmp = armcpu->CPSR;
armcpu_switchMode(armcpu, IRQ);
#ifdef GDB_STUB
armcpu->R[14] = armcpu->next_instruction + 4;
#else
armcpu->R[14] = armcpu->instruct_adr + 4;
#endif
armcpu->SPSR = tmp;
armcpu->CPSR.bits.T = 0;
armcpu->CPSR.bits.I = 1;
armcpu->next_instruction = armcpu->intVector + 0x18;
armcpu->waitIRQ = 0;
#ifndef GDB_STUB
armcpu->R[15] = armcpu->next_instruction + 8;
armcpu_prefetch(armcpu);
#endif
return TRUE;
}
/*
static BOOL armcpu_prefetchExeption(armcpu_t *armcpu)
{
Status_Reg tmp;
if(armcpu->CPSR.bits.I) return FALSE;
tmp = armcpu->CPSR;
armcpu_switchMode(armcpu, ABT);
armcpu->R[14] = armcpu->next_instruction + 4;
armcpu->SPSR = tmp;
armcpu->CPSR.bits.T = 0;
armcpu->CPSR.bits.I = 1;
armcpu->next_instruction = armcpu->intVector + 0xC;
armcpu->R[15] = armcpu->next_instruction + 8;
armcpu->waitIRQ = 0;
return TRUE;
}
*/
static BOOL armcpu_prefetchExeption(armcpu_t *armcpu)
{
Status_Reg tmp;
if(armcpu->CPSR.bits.I) return FALSE;
tmp = armcpu->CPSR;
armcpu_switchMode(armcpu, ABT);
#ifdef GDB_STUB
armcpu->R[14] = armcpu->next_instruction + 4;
#else
armcpu->R[14] = armcpu->instruct_adr + 4;
#endif
armcpu->SPSR = tmp;
armcpu->CPSR.bits.T = 0;
armcpu->CPSR.bits.I = 1;
armcpu->next_instruction = armcpu->intVector + 0xC;
armcpu->waitIRQ = 0;
#ifdef GDB_STUB
armcpu->R[15] = armcpu->next_instruction + 8;
#else
armcpu->R[15] = armcpu->next_instruction;
armcpu_prefetch(armcpu);
#endif
return TRUE;
}
BOOL
armcpu_flagIrq( armcpu_t *armcpu) {
if(armcpu->CPSR.bits.I) return FALSE;
armcpu->waitIRQ = 0;
#ifdef GDB_STUB
armcpu->irq_flag = 1;
#endif
return TRUE;
}
u32 armcpu_exec(armcpu_t *armcpu)
{
u32 c = 1;
#ifdef GDB_STUB
if ( armcpu->stalled)
return STALLED_CYCLE_COUNT;
/* check for interrupts */
if ( armcpu->irq_flag) {
armcpu_irqExeption( armcpu);
}
c = armcpu_prefetch(armcpu);
if ( armcpu->stalled) {
return c;
}
#endif
if(armcpu->CPSR.bits.T == 0)
{
/* if((TEST_COND(CONDITION(armcpu->instruction), armcpu->CPSR)) || ((CONDITION(armcpu->instruction)==0xF)&&(CODE(armcpu->instruction)==0x5)))*/
if((TEST_COND(CONDITION(armcpu->instruction), CODE(armcpu->instruction), armcpu->CPSR)))
{
c += arm_instructions_set[INSTRUCTION_INDEX(armcpu->instruction)](armcpu);
}
#ifdef GDB_STUB
if ( armcpu->post_ex_fn != NULL) {
/* call the external post execute function */
armcpu->post_ex_fn( armcpu->post_ex_fn_data,
armcpu->instruct_adr, 0);
}
#else
c += armcpu_prefetch(armcpu);
#endif
return c;
}
c += thumb_instructions_set[armcpu->instruction>>6](armcpu);
#ifdef GDB_STUB
if ( armcpu->post_ex_fn != NULL) {
/* call the external post execute function */
armcpu->post_ex_fn( armcpu->post_ex_fn_data, armcpu->instruct_adr, 1);
}
#else
c += armcpu_prefetch(armcpu);
#endif
return c;
}

View File

@ -0,0 +1,288 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef ARM_CPU
#define ARM_CPU
#include "types.h"
#include "bits.h"
#include "MMU.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ARMCPU_ARM7 1
#define ARMCPU_ARM9 0
#define CODE(i) (((i)>>25)&0X7)
#define OPCODE(i) (((i)>>21)&0xF)
#define SIGNEBIT(i) BIT_N(i,20)
#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
#define ROR(i, j) ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j))))
#define UNSIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)) | \
((BIT31(a)|BIT31(b))&BIT31(~c)))
#define UNSIGNED_UNDERFLOW(a,b,c) ((BIT31(~a)&BIT31(b)) | \
((BIT31(~a)|BIT31(b))&BIT31(c)))
#define SIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)&BIT31(~c))|\
(BIT31(~a)&BIT31(~(b))&BIT31(c)))
#define SIGNED_UNDERFLOW(a,b,c) ((BIT31(a)&BIT31(~(b))&BIT31(~c))|\
(BIT31(~a)&BIT31(b)&BIT31(c)))
#define EQ 0x0
#define NE 0x1
#define CS 0x2
#define CC 0x3
#define MI 0x4
#define PL 0x5
#define VS 0x6
#define VC 0x7
#define HI 0x8
#define LS 0x9
#define GE 0xA
#define LT 0xB
#define GT 0xC
#define LE 0xD
#define AL 0xE
/*
#define TEST_COND(cond, CPSR) (((cond)==AL) ||\
(((cond)==EQ) && ( CPSR.bits.Z))||\
(((cond)==NE) && (!CPSR.bits.Z))||\
(((cond)==CS) && ( CPSR.bits.C))||\
(((cond)==CC) && (!CPSR.bits.C))||\
(((cond)==MI) && ( CPSR.bits.N))||\
(((cond)==PL) && (!CPSR.bits.N))||\
(((cond)==VS) && ( CPSR.bits.V))||\
(((cond)==VC) && (!CPSR.bits.V))||\
(((cond)==HI) && (CPSR.bits.C) && (!CPSR.bits.Z))||\
(((cond)==LS) && ((CPSR.bits.Z) || (!CPSR.bits.C)))||\
(((cond)==GE) && (CPSR.bits.N==CPSR.bits.V))||\
(((cond)==LT) && (CPSR.bits.N!=CPSR.bits.V))||\
(((cond)==GT) && (CPSR.bits.Z==0) && (CPSR.bits.N==CPSR.bits.V))||\
(((cond)==LE) && ((CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V))))
*/
extern const unsigned char arm_cond_table[16*16];
#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)+(cond)] >> (inst)) & 1)
enum Mode
{
USR = 0x10,
FIQ = 0x11,
IRQ = 0x12,
SVC = 0x13,
ABT = 0x17,
UND = 0x1B,
SYS = 0x1F
};
#ifdef WORDS_BIGENDIAN
typedef union
{
struct
{
u32 N : 1,
Z : 1,
C : 1,
V : 1,
Q : 1,
RAZ : 19,
I : 1,
F : 1,
T : 1,
mode : 5;
} bits;
u32 val;
} Status_Reg;
#else
typedef union
{
struct
{
u32 mode : 5,
T : 1,
F : 1,
I : 1,
RAZ : 19,
Q : 1,
V : 1,
C : 1,
Z : 1,
N : 1;
} bits;
u32 val;
} Status_Reg;
#endif
/**
* The control interface to a CPU
*/
struct armcpu_ctrl_iface {
/** stall the processor */
void (*stall)( void *instance);
/** unstall the processor */
void (*unstall)( void *instance);
/** read a register value */
u32 (*read_reg)( void *instance, u32 reg_num);
/** set a register value */
void (*set_reg)( void *instance, u32 reg_num, u32 value);
/** install the post execute function */
void (*install_post_ex_fn)( void *instance,
void (*fn)( void *, u32 adr, int thumb),
void *fn_data);
/** remove the post execute function */
void (*remove_post_ex_fn)( void *instance);
/** the private data passed to all interface functions */
void *data;
};
typedef void* armcp_t;
typedef struct armcpu_t
{
u32 proc_ID;
u32 instruction; //4
u32 instruct_adr; //8
u32 next_instruction; //12
u32 R[16]; //16
Status_Reg CPSR; //80
Status_Reg SPSR;
u32 R13_usr, R14_usr;
u32 R13_svc, R14_svc;
u32 R13_abt, R14_abt;
u32 R13_und, R14_und;
u32 R13_irq, R14_irq;
u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq;
Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq;
armcp_t *coproc[16];
u32 intVector;
u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5
BOOL waitIRQ;
BOOL wIRQ;
BOOL wirq;
u32 (* *swi_tab)(struct armcpu_t * cpu);
#ifdef GDB_STUB
/** there is a pending irq for the cpu */
int irq_flag;
/** the post executed function (if installed) */
void (*post_ex_fn)( void *, u32 adr, int thumb);
/** data for the post executed function */
void *post_ex_fn_data;
/** flag indicating if the processor is stalled */
int stalled;
/** the memory interface */
struct armcpu_memory_iface *mem_if;
/** the ctrl interface */
struct armcpu_ctrl_iface ctrl_iface;
#endif
} armcpu_t;
#ifdef GDB_STUB
int armcpu_new( armcpu_t *armcpu, u32 id, struct armcpu_memory_iface *mem_if,
struct armcpu_ctrl_iface **ctrl_iface_ret);
#else
int armcpu_new( armcpu_t *armcpu, u32 id);
#endif
void armcpu_init(armcpu_t *armcpu, u32 adr);
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode);
static u32 armcpu_prefetch(armcpu_t *armcpu);
u32 armcpu_exec(armcpu_t *armcpu);
BOOL armcpu_irqExeption(armcpu_t *armcpu);
//BOOL armcpu_prefetchExeption(armcpu_t *armcpu);
BOOL
armcpu_flagIrq( armcpu_t *armcpu);
extern armcpu_t NDS_ARM7;
extern armcpu_t NDS_ARM9;
static INLINE void NDS_makeARM9Int(u32 num)
{
/* flag the interrupt request source */
MMU.reg_IF[0] |= (1<<num);
/* generate the interrupt if enabled */
if ((MMU.reg_IE[0] & (1 << num)) && MMU.reg_IME[0])
{
NDS_ARM9.wIRQ = TRUE;
NDS_ARM9.waitIRQ = FALSE;
}
}
static INLINE void NDS_makeARM7Int(u32 num)
{
/* flag the interrupt request source */
MMU.reg_IF[1] |= (1<<num);
/* generate the interrupt if enabled */
if ((MMU.reg_IE[1] & (1 << num)) && MMU.reg_IME[1])
{
NDS_ARM7.wIRQ = TRUE;
NDS_ARM7.waitIRQ = FALSE;
}
}
static INLINE void NDS_makeInt(u8 proc_ID,u32 num)
{
switch (proc_ID)
{
case 0:
NDS_makeARM9Int(num) ;
break ;
case 1:
NDS_makeARM7Int(num) ;
break ;
}
}
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef BIOS_H
#define BIOS_H
#include "armcpu.h"
extern u32 (* ARM9_swi_tab[32])(armcpu_t * cpu);
extern u32 (* ARM7_swi_tab[32])(armcpu_t * cpu);
extern u32 wait4IRQ(armcpu_t * cpu);
#endif

View File

@ -0,0 +1,44 @@
#ifndef BITS_H
#define BITS_H
#define BIT(n) (1<<(n))
#define BIT_N(i,n) (((i)>>(n))&1)
#define BIT0(i) ((i)&1)
#define BIT1(i) BIT_N(i,1)
#define BIT2(i) BIT_N(i,2)
#define BIT3(i) BIT_N(i,3)
#define BIT4(i) BIT_N(i,4)
#define BIT5(i) BIT_N(i,5)
#define BIT6(i) BIT_N(i,6)
#define BIT7(i) BIT_N(i,7)
#define BIT8(i) BIT_N(i,8)
#define BIT9(i) BIT_N(i,9)
#define BIT10(i) BIT_N(i,10)
#define BIT11(i) BIT_N(i,11)
#define BIT12(i) BIT_N(i,12)
#define BIT13(i) BIT_N(i,13)
#define BIT14(i) BIT_N(i,14)
#define BIT15(i) BIT_N(i,15)
#define BIT16(i) BIT_N(i,16)
#define BIT17(i) BIT_N(i,17)
#define BIT18(i) BIT_N(i,18)
#define BIT19(i) BIT_N(i,19)
#define BIT20(i) BIT_N(i,20)
#define BIT21(i) BIT_N(i,21)
#define BIT22(i) BIT_N(i,22)
#define BIT23(i) BIT_N(i,23)
#define BIT24(i) BIT_N(i,24)
#define BIT25(i) BIT_N(i,25)
#define BIT26(i) BIT_N(i,26)
#define BIT27(i) BIT_N(i,27)
#define BIT28(i) BIT_N(i,28)
#define BIT29(i) BIT_N(i,29)
#define BIT30(i) BIT_N(i,30)
#define BIT31(i) ((i)>>31)
#define CONDITION(i) (i)>>28
#define REG_POS(i,n) (((i)>>n)&0xF)
#endif

View File

@ -0,0 +1,28 @@
/* Copyright (C) 2006 thoduv
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __CONFIG_H__
#define __CONFIG_H__
#include <stdio.h>
#include "debug.h"
#endif /*__CONFIG_H__*/

View File

@ -0,0 +1,590 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include "cp15.h"
#include "debug.h"
#include "MMU.h"
armcp15_t *armcp15_new(armcpu_t * c)
{
int i;
armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t));
if(!armcp15) return NULL;
armcp15->cpu = c;
armcp15->IDCode = 0x41049460;
armcp15->cacheType = 0x0F0D2112;
armcp15->TCMSize = 0x00140140;
armcp15->ctrl = 0x00000000;
armcp15->DCConfig = 0x0;
armcp15->ICConfig = 0x0;
armcp15->writeBuffCtrl = 0x0;
armcp15->und = 0x0;
armcp15->DaccessPerm = 0x22222222;
armcp15->IaccessPerm = 0x22222222;
armcp15->protectBaseSize0 = 0x0;
armcp15->protectBaseSize1 = 0x0;
armcp15->protectBaseSize2 = 0x0;
armcp15->protectBaseSize3 = 0x0;
armcp15->protectBaseSize4 = 0x0;
armcp15->protectBaseSize5 = 0x0;
armcp15->protectBaseSize6 = 0x0;
armcp15->protectBaseSize7 = 0x0;
armcp15->cacheOp = 0x0;
armcp15->DcacheLock = 0x0;
armcp15->IcacheLock = 0x0;
armcp15->ITCMRegion = 0x0C;
armcp15->DTCMRegion = 0x0080000A;
armcp15->processID = 0;
/* preset calculated regionmasks */
for (i=0;i<8;i++) {
armcp15->regionWriteMask_USR[i] = 0 ;
armcp15->regionWriteMask_SYS[i] = 0 ;
armcp15->regionReadMask_USR[i] = 0 ;
armcp15->regionReadMask_SYS[i] = 0 ;
armcp15->regionExecuteMask_USR[i] = 0 ;
armcp15->regionExecuteMask_SYS[i] = 0 ;
armcp15->regionWriteSet_USR[i] = 0 ;
armcp15->regionWriteSet_SYS[i] = 0 ;
armcp15->regionReadSet_USR[i] = 0 ;
armcp15->regionReadSet_SYS[i] = 0 ;
armcp15->regionExecuteSet_USR[i] = 0 ;
armcp15->regionExecuteSet_SYS[i] = 0 ;
} ;
return armcp15;
}
#define ACCESSTYPE(val,n) (((val) >> (4*n)) & 0x0F)
#define SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F))
#define SIZEBINARY(val) (1 << (SIZEIDENTIFIER(val)+1))
#define MASKFROMREG(val) (~((SIZEBINARY(val)-1) | 0x3F))
#define SETFROMREG(val) ((val) & MASKFROMREG(val))
/* sets the precalculated regions to mask,set for the affected accesstypes */
void armcp15_setSingleRegionAccess(armcp15_t *armcp15,unsigned long dAccess,unsigned long iAccess,unsigned char num, unsigned long mask,unsigned long set) {
switch (ACCESSTYPE(dAccess,num)) {
case 4: /* UNP */
case 7: /* UNP */
case 8: /* UNP */
case 9: /* UNP */
case 10: /* UNP */
case 11: /* UNP */
case 12: /* UNP */
case 13: /* UNP */
case 14: /* UNP */
case 15: /* UNP */
case 0: /* no access at all */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = 0 ;
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionWriteMask_SYS[num] = 0 ;
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_SYS[num] = 0 ;
armcp15->regionReadSet_SYS[num] = 0xFFFFFFFF ;
break ;
case 1: /* no access at USR, all to sys */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = 0 ;
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionWriteMask_SYS[num] = mask ;
armcp15->regionWriteSet_SYS[num] = set ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
break ;
case 2: /* read at USR, all to sys */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = mask ;
armcp15->regionReadSet_USR[num] = set ;
armcp15->regionWriteMask_SYS[num] = mask ;
armcp15->regionWriteSet_SYS[num] = set ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
break ;
case 3: /* all to USR, all to sys */
armcp15->regionWriteMask_USR[num] = mask ;
armcp15->regionWriteSet_USR[num] = set ;
armcp15->regionReadMask_USR[num] = mask ;
armcp15->regionReadSet_USR[num] = set ;
armcp15->regionWriteMask_SYS[num] = mask ;
armcp15->regionWriteSet_SYS[num] = set ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
break ;
case 5: /* no access at USR, read to sys */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = 0 ;
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionWriteMask_SYS[num] = 0 ;
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
break ;
case 6: /* read at USR, read to sys */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = mask ;
armcp15->regionReadSet_USR[num] = set ;
armcp15->regionWriteMask_SYS[num] = 0 ;
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
break ;
}
switch (ACCESSTYPE(iAccess,num)) {
case 4: /* UNP */
case 7: /* UNP */
case 8: /* UNP */
case 9: /* UNP */
case 10: /* UNP */
case 11: /* UNP */
case 12: /* UNP */
case 13: /* UNP */
case 14: /* UNP */
case 15: /* UNP */
case 0: /* no access at all */
armcp15->regionExecuteMask_USR[num] = 0 ;
armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionExecuteMask_SYS[num] = 0 ;
armcp15->regionExecuteSet_SYS[num] = 0xFFFFFFFF ;
break ;
case 1:
armcp15->regionExecuteMask_USR[num] = 0 ;
armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionExecuteMask_SYS[num] = mask ;
armcp15->regionExecuteSet_SYS[num] = set ;
break ;
case 2:
case 3:
case 6:
armcp15->regionExecuteMask_USR[num] = mask ;
armcp15->regionExecuteSet_USR[num] = set ;
armcp15->regionExecuteMask_SYS[num] = mask ;
armcp15->regionExecuteSet_SYS[num] = set ;
break ;
}
} ;
/* precalculate region masks/sets from cp15 register */
void armcp15_maskPrecalc(armcp15_t *armcp15)
{
#define precalc(num) { \
u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \
if (BIT_N(armcp15->protectBaseSize##num,0)) /* if region is enabled */ \
{ /* reason for this define: naming includes var */ \
mask = MASKFROMREG(armcp15->protectBaseSize##num) ; \
set = SETFROMREG(armcp15->protectBaseSize##num) ; \
if (SIZEIDENTIFIER(armcp15->protectBaseSize##num)==0x1F) \
{ /* for the 4GB region, u32 suffers wraparound */ \
mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \
} \
} \
armcp15_setSingleRegionAccess(armcp15,armcp15->DaccessPerm,armcp15->IaccessPerm,num,mask,set) ; \
}
precalc(0) ;
precalc(1) ;
precalc(2) ;
precalc(3) ;
precalc(4) ;
precalc(5) ;
precalc(6) ;
precalc(7) ;
}
INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access)
{
int i ;
if (!(armcp15->ctrl & 1)) return TRUE ; /* protection checking is not enabled */
for (i=0;i<8;i++) {
switch (access) {
case CP15_ACCESS_WRITEUSR:
if ((address & armcp15->regionWriteMask_USR[i]) == armcp15->regionWriteSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_WRITESYS:
if ((address & armcp15->regionWriteMask_SYS[i]) == armcp15->regionWriteSet_SYS[i]) return TRUE ;
break ;
case CP15_ACCESS_READUSR:
if ((address & armcp15->regionReadMask_USR[i]) == armcp15->regionReadSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_READSYS:
if ((address & armcp15->regionReadMask_SYS[i]) == armcp15->regionReadSet_SYS[i]) return TRUE ;
break ;
case CP15_ACCESS_EXECUSR:
if ((address & armcp15->regionExecuteMask_USR[i]) == armcp15->regionExecuteSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_EXECSYS:
if ((address & armcp15->regionExecuteMask_SYS[i]) == armcp15->regionExecuteSet_SYS[i]) return TRUE ;
break ;
}
}
/* when protections are enabled, but no region allows access, deny access */
return FALSE ;
}
BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
return FALSE;
}
BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr)
{
return FALSE;
}
BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr)
{
return FALSE;
}
BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE;
switch(CRn)
{
case 0 :
if((opcode1 == 0)&&(CRm==0))
{
switch(opcode2)
{
case 1 :
*R = armcp15->cacheType;
return TRUE;
case 2 :
*R = armcp15->TCMSize;
return TRUE;
default :
*R = armcp15->IDCode;
return TRUE;
}
}
return FALSE;
case 1 :
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
*R = armcp15->ctrl;
return TRUE;
}
return FALSE;
case 2 :
if((opcode1==0) && (CRm==0))
{
switch(opcode2)
{
case 0 :
*R = armcp15->DCConfig;
return TRUE;
case 1 :
*R = armcp15->ICConfig;
return TRUE;
default :
return FALSE;
}
}
return FALSE;
case 3 :
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
*R = armcp15->writeBuffCtrl;
return TRUE;
}
return FALSE;
case 5 :
if((opcode1==0) && (CRm==0))
{
switch(opcode2)
{
case 2 :
*R = armcp15->DaccessPerm;
return TRUE;
case 3 :
*R = armcp15->IaccessPerm;
return TRUE;
default :
return FALSE;
}
}
return FALSE;
case 6 :
if((opcode1==0) && (opcode2==0))
{
switch(CRm)
{
case 0 :
*R = armcp15->protectBaseSize0;
return TRUE;
case 1 :
*R = armcp15->protectBaseSize1;
return TRUE;
case 2 :
*R = armcp15->protectBaseSize2;
return TRUE;
case 3 :
*R = armcp15->protectBaseSize3;
return TRUE;
case 4 :
*R = armcp15->protectBaseSize4;
return TRUE;
case 5 :
*R = armcp15->protectBaseSize5;
return TRUE;
case 6 :
*R = armcp15->protectBaseSize6;
return TRUE;
case 7 :
*R = armcp15->protectBaseSize7;
return TRUE;
default :
return FALSE;
}
}
return FALSE;
case 9 :
if((opcode1==0))
{
switch(CRm)
{
case 0 :
switch(opcode2)
{
case 0 :
*R = armcp15->DcacheLock;
return TRUE;
case 1 :
*R = armcp15->IcacheLock;
return TRUE;
default :
return FALSE;
}
case 1 :
switch(opcode2)
{
case 0 :
*R = armcp15->DTCMRegion;
return TRUE;
case 1 :
*R = armcp15->ITCMRegion;
return TRUE;
default :
return FALSE;
}
}
}
return FALSE;
default :
return FALSE;
}
}
u32 CP15wait4IRQ(armcpu_t *cpu)
{
/* on the first call, wirq is not set */
if(cpu->wirq)
{
/* check wether an irq was issued */
if(!cpu->waitIRQ)
{
cpu->waitIRQ = 0;
cpu->wirq = 0;
return 1; /* return execution */
}
/* otherwise, repeat this instruction */
cpu->R[15] = cpu->instruct_adr;
cpu->next_instruction = cpu->R[15];
return 1;
}
/* first run, set us into waiting state */
cpu->waitIRQ = 1;
cpu->wirq = 1;
/* and set next instruction to repeat this */
cpu->R[15] = cpu->instruct_adr;
cpu->next_instruction = cpu->R[15];
/* CHECKME: IME shouldn't be modified (?) */
MMU.reg_IME[0] = 1;
return 1;
}
BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE;
switch(CRn)
{
case 1 :
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
armcp15->ctrl = val;
MMU.ARM9_RW_MODE = BIT7(val);
armcp15->cpu->intVector = 0x0FFF0000 * (BIT13(val));
armcp15->cpu->LDTBit = !BIT15(val); //TBit
/*if(BIT17(val))
{
log::ajouter("outch !!!!!!!");
}
if(BIT19(val))
{
log::ajouter("outch !!!!!!!");
}*/
return TRUE;
}
return FALSE;
case 2 :
if((opcode1==0) && (CRm==0))
{
switch(opcode2)
{
case 0 :
armcp15->DCConfig = val;
return TRUE;
case 1 :
armcp15->ICConfig = val;
return TRUE;
default :
return FALSE;
}
}
return FALSE;
case 3 :
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
armcp15->writeBuffCtrl = val;
return TRUE;
}
return FALSE;
if((opcode1==0) && (CRm==0))
{
switch(opcode2)
{
case 2 :
armcp15->DaccessPerm = val;
armcp15_maskPrecalc(armcp15);
return TRUE;
case 3 :
armcp15->IaccessPerm = val;
armcp15_maskPrecalc(armcp15);
return TRUE;
default :
return FALSE;
}
}
return FALSE;
case 6 :
if((opcode1==0) && (opcode2==0))
{
switch(CRm)
{
case 0 :
armcp15->protectBaseSize0 = val;
armcp15_maskPrecalc(armcp15) ;
return TRUE;
case 1 :
armcp15->protectBaseSize1 = val;
armcp15_maskPrecalc(armcp15) ;
return TRUE;
case 2 :
armcp15->protectBaseSize2 = val;
armcp15_maskPrecalc(armcp15) ;
return TRUE;
case 3 :
armcp15->protectBaseSize3 = val;
armcp15_maskPrecalc(armcp15) ;
return TRUE;
case 4 :
armcp15->protectBaseSize4 = val;
armcp15_maskPrecalc(armcp15) ;
return TRUE;
case 5 :
armcp15->protectBaseSize5 = val;
armcp15_maskPrecalc(armcp15) ;
return TRUE;
case 6 :
armcp15->protectBaseSize6 = val;
armcp15_maskPrecalc(armcp15) ;
return TRUE;
case 7 :
armcp15->protectBaseSize7 = val;
armcp15_maskPrecalc(armcp15) ;
return TRUE;
default :
return FALSE;
}
}
return FALSE;
case 7 :
if((CRm==0)&&(opcode1==0)&&((opcode2==4)))
{
CP15wait4IRQ(armcp15->cpu);
return TRUE;
}
return FALSE;
case 9 :
if((opcode1==0))
{
switch(CRm)
{
case 0 :
switch(opcode2)
{
case 0 :
armcp15->DcacheLock = val;
return TRUE;
case 1 :
armcp15->IcacheLock = val;
return TRUE;
default :
return FALSE;
}
case 1 :
switch(opcode2)
{
case 0 :
armcp15->DTCMRegion = val;
MMU.DTCMRegion = val & 0x0FFFFFFC0;
/*sprintf(logbuf, "%08X", val);
log::ajouter(logbuf);*/
return TRUE;
case 1 :
armcp15->ITCMRegion = val;
/* ITCM base is not writeable! */
MMU.ITCMRegion = 0;
return TRUE;
default :
return FALSE;
}
}
}
return FALSE;
default :
return FALSE;
}
}

View File

@ -0,0 +1,94 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __CP15_H__
#define __CP15_H__
#include "armcpu.h"
typedef struct
{
u32 IDCode;
u32 cacheType;
u32 TCMSize;
u32 ctrl;
u32 DCConfig;
u32 ICConfig;
u32 writeBuffCtrl;
u32 und;
u32 DaccessPerm;
u32 IaccessPerm;
u32 protectBaseSize0;
u32 protectBaseSize1;
u32 protectBaseSize2;
u32 protectBaseSize3;
u32 protectBaseSize4;
u32 protectBaseSize5;
u32 protectBaseSize6;
u32 protectBaseSize7;
u32 cacheOp;
u32 DcacheLock;
u32 IcacheLock;
u32 ITCMRegion;
u32 DTCMRegion;
u32 processID;
u32 RAM_TAG;
u32 testState;
u32 cacheDbg;
/* calculated bitmasks for the regions to decide rights uppon */
/* calculation is done in the MCR instead of on mem access for performance */
u32 regionWriteMask_USR[8] ;
u32 regionWriteMask_SYS[8] ;
u32 regionReadMask_USR[8] ;
u32 regionReadMask_SYS[8] ;
u32 regionExecuteMask_USR[8] ;
u32 regionExecuteMask_SYS[8] ;
u32 regionWriteSet_USR[8] ;
u32 regionWriteSet_SYS[8] ;
u32 regionReadSet_USR[8] ;
u32 regionReadSet_SYS[8] ;
u32 regionExecuteSet_USR[8] ;
u32 regionExecuteSet_SYS[8] ;
armcpu_t * cpu;
} armcp15_t;
armcp15_t *armcp15_new(armcpu_t *c);
BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr);
BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr);
BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) ;
#define CP15_ACCESS_WRITE 0
#define CP15_ACCESS_READ 2
#define CP15_ACCESS_EXECUTE 4
#define CP15_ACCESS_WRITEUSR CP15_ACCESS_WRITE
#define CP15_ACCESS_WRITESYS 1
#define CP15_ACCESS_READUSR CP15_ACCESS_READ
#define CP15_ACCESS_READSYS 3
#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE
#define CP15_ACCESS_EXECSYS 5
#endif /* __CP15_H__*/

View File

@ -0,0 +1,11 @@
#ifndef DEBUG_H
#define DEBUG_H
#define LOG(x)
#define GPULOG(x)
#define DIVLOG(x)
#define SQRTLOG(x)
#define CARDLOG(x)
#define DMALOG(x)
#endif

View File

@ -0,0 +1,34 @@
/* Copyright (C) 2006 thoduv
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __DSCARD_H__
#define __DSCARD_H__
typedef struct
{
u32 adress;
u32 transfer_count;
} nds_dscard;
#endif /*__DSCARD_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,257 @@
/*
Copyright (C) 2006-2007 shash
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "matrix.h"
void MatrixInit (float *matrix)
{
memset (matrix, 0, sizeof(float)*16);
matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
}
void MatrixMultVec4x4 (float *matrix, float *vecPtr)
{
float x = vecPtr[0];
float y = vecPtr[1];
float z = vecPtr[2];
vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8] + matrix[12];
vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9] + matrix[13];
vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14];
}
void MatrixMultVec3x3 (float *matrix, float *vecPtr)
{
float x = vecPtr[0];
float y = vecPtr[1];
float z = vecPtr[2];
vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8];
vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9];
vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10];
}
void MatrixIdentity (float *matrix)
{
memset (matrix, 0, sizeof(float)*16);
matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
}
void MatrixMultiply (float *matrix, float *rightMatrix)
{
float tmpMatrix[16];
tmpMatrix[0] = (matrix[0]*rightMatrix[0])+(matrix[4]*rightMatrix[1])+(matrix[8]*rightMatrix[2])+(matrix[12]*rightMatrix[3]);
tmpMatrix[1] = (matrix[1]*rightMatrix[0])+(matrix[5]*rightMatrix[1])+(matrix[9]*rightMatrix[2])+(matrix[13]*rightMatrix[3]);
tmpMatrix[2] = (matrix[2]*rightMatrix[0])+(matrix[6]*rightMatrix[1])+(matrix[10]*rightMatrix[2])+(matrix[14]*rightMatrix[3]);
tmpMatrix[3] = (matrix[3]*rightMatrix[0])+(matrix[7]*rightMatrix[1])+(matrix[11]*rightMatrix[2])+(matrix[15]*rightMatrix[3]);
tmpMatrix[4] = (matrix[0]*rightMatrix[4])+(matrix[4]*rightMatrix[5])+(matrix[8]*rightMatrix[6])+(matrix[12]*rightMatrix[7]);
tmpMatrix[5] = (matrix[1]*rightMatrix[4])+(matrix[5]*rightMatrix[5])+(matrix[9]*rightMatrix[6])+(matrix[13]*rightMatrix[7]);
tmpMatrix[6] = (matrix[2]*rightMatrix[4])+(matrix[6]*rightMatrix[5])+(matrix[10]*rightMatrix[6])+(matrix[14]*rightMatrix[7]);
tmpMatrix[7] = (matrix[3]*rightMatrix[4])+(matrix[7]*rightMatrix[5])+(matrix[11]*rightMatrix[6])+(matrix[15]*rightMatrix[7]);
tmpMatrix[8] = (matrix[0]*rightMatrix[8])+(matrix[4]*rightMatrix[9])+(matrix[8]*rightMatrix[10])+(matrix[12]*rightMatrix[11]);
tmpMatrix[9] = (matrix[1]*rightMatrix[8])+(matrix[5]*rightMatrix[9])+(matrix[9]*rightMatrix[10])+(matrix[13]*rightMatrix[11]);
tmpMatrix[10] = (matrix[2]*rightMatrix[8])+(matrix[6]*rightMatrix[9])+(matrix[10]*rightMatrix[10])+(matrix[14]*rightMatrix[11]);
tmpMatrix[11] = (matrix[3]*rightMatrix[8])+(matrix[7]*rightMatrix[9])+(matrix[11]*rightMatrix[10])+(matrix[15]*rightMatrix[11]);
tmpMatrix[12] = (matrix[0]*rightMatrix[12])+(matrix[4]*rightMatrix[13])+(matrix[8]*rightMatrix[14])+(matrix[12]*rightMatrix[15]);
tmpMatrix[13] = (matrix[1]*rightMatrix[12])+(matrix[5]*rightMatrix[13])+(matrix[9]*rightMatrix[14])+(matrix[13]*rightMatrix[15]);
tmpMatrix[14] = (matrix[2]*rightMatrix[12])+(matrix[6]*rightMatrix[13])+(matrix[10]*rightMatrix[14])+(matrix[14]*rightMatrix[15]);
tmpMatrix[15] = (matrix[3]*rightMatrix[12])+(matrix[7]*rightMatrix[13])+(matrix[11]*rightMatrix[14])+(matrix[15]*rightMatrix[15]);
memcpy (matrix, tmpMatrix, sizeof(float)*16);
}
/*
void MatrixMulti (float* right)
{
float tmpMatrix[16];
tmpMatrix[0] = (matrix[0]*right[0])+(matrix[4]*right[1])+(matrix[8]*right[2])+(matrix[12]*right[3]);
tmpMatrix[1] = (matrix[1]*right[0])+(matrix[5]*right[1])+(matrix[9]*right[2])+(matrix[13]*right[3]);
tmpMatrix[2] = (matrix[2]*right[0])+(matrix[6]*right[1])+(matrix[10]*right[2])+(matrix[14]*right[3]);
tmpMatrix[3] = (matrix[3]*right[0])+(matrix[7]*right[1])+(matrix[11]*right[2])+(matrix[15]*right[3]);
tmpMatrix[4] = (matrix[0]*right[4])+(matrix[4]*right[5])+(matrix[8]*right[6])+(matrix[12]*right[7]);
tmpMatrix[5] = (matrix[1]*right[4])+(matrix[5]*right[5])+(matrix[9]*right[6])+(matrix[13]*right[7]);
tmpMatrix[6] = (matrix[2]*right[4])+(matrix[6]*right[5])+(matrix[10]*right[6])+(matrix[14]*right[7]);
tmpMatrix[7] = (matrix[3]*right[4])+(matrix[7]*right[5])+(matrix[11]*right[6])+(matrix[15]*right[7]);
tmpMatrix[8] = (matrix[0]*right[8])+(matrix[4]*right[9])+(matrix[8]*right[10])+(matrix[12]*right[11]);
tmpMatrix[9] = (matrix[1]*right[8])+(matrix[5]*right[9])+(matrix[9]*right[10])+(matrix[13]*right[11]);
tmpMatrix[10] = (matrix[2]*right[8])+(matrix[6]*right[9])+(matrix[10]*right[10])+(matrix[14]*right[11]);
tmpMatrix[11] = (matrix[3]*right[8])+(matrix[7]*right[9])+(matrix[11]*right[10])+(matrix[15]*right[11]);
tmpMatrix[12] = (matrix[0]*right[12])+(matrix[4]*right[13])+(matrix[8]*right[14])+(matrix[12]*right[15]);
tmpMatrix[13] = (matrix[1]*right[12])+(matrix[5]*right[13])+(matrix[9]*right[14])+(matrix[13]*right[15]);
tmpMatrix[14] = (matrix[2]*right[12])+(matrix[6]*right[13])+(matrix[10]*right[14])+(matrix[14]*right[15]);
tmpMatrix[15] = (matrix[3]*right[12])+(matrix[7]*right[13])+(matrix[11]*right[14])+(matrix[15]*right[15]);
memcpy (matrix, tmpMatrix, sizeof(float)*16);
}
float* Matrix::Get (void)
{
return matrix;
}
float MatrixGet (float *matrix, int index)
{
return matrix[index];
}
*/
float MatrixGetMultipliedIndex (int index, float *matrix, float *rightMatrix)
{
int iMod = index%4, iDiv = (index>>2)<<2;
return (matrix[iMod ]*rightMatrix[iDiv ])+(matrix[iMod+ 4]*rightMatrix[iDiv+1])+
(matrix[iMod+8]*rightMatrix[iDiv+2])+(matrix[iMod+12]*rightMatrix[iDiv+3]);
}
void MatrixSet (float *matrix, int x, int y, float value)
{
matrix [x+(y<<2)] = value;
}
/*
void Matrix::Set (int pos, float value)
{
matrix [pos] = value;
}
*/
void MatrixCopy (float *matrixDST, float *matrixSRC)
{
memcpy (matrixDST, matrixSRC, sizeof(float)*16);
}
void MatrixTranslate (float *matrix, float *ptr)
{
matrix[12] += (matrix[0]*ptr[0])+(matrix[4]*ptr[1])+(matrix[ 8]*ptr[2]);
matrix[13] += (matrix[1]*ptr[0])+(matrix[5]*ptr[1])+(matrix[ 9]*ptr[2]);
matrix[14] += (matrix[2]*ptr[0])+(matrix[6]*ptr[1])+(matrix[10]*ptr[2]);
matrix[15] += (matrix[3]*ptr[0])+(matrix[7]*ptr[1])+(matrix[11]*ptr[2]);
}
void MatrixScale (float *matrix, float *ptr)
{
matrix[0] *= ptr[0];
matrix[1] *= ptr[0];
matrix[2] *= ptr[0];
matrix[3] *= ptr[0];
matrix[4] *= ptr[1];
matrix[5] *= ptr[1];
matrix[6] *= ptr[1];
matrix[7] *= ptr[1];
matrix[8] *= ptr[2];
matrix[9] *= ptr[2];
matrix[10] *= ptr[2];
matrix[11] *= ptr[2];
}
/*
void Matrix::Set (float a11, float a21, float a31, float a41,
float a12, float a22, float a32, float a42,
float a13, float a23, float a33, float a43,
float a14, float a24, float a34, float a44)
{
}
*/
//-----------------------------------------
void MatrixStackInit (MatrixStack *stack)
{
stack->matrix = NULL;
stack->position = 0;
stack->size = 0;
}
void MatrixStackSetMaxSize (MatrixStack *stack, int size)
{
int i = 0;
stack->size = size;
if (stack->matrix == NULL)
{
stack->matrix = (float*) malloc (stack->size*16*sizeof(float));
}
else
{
free (stack->matrix);
stack->matrix = (float*) malloc (stack->size*16*sizeof(float));
}
for (i = 0; i < stack->size; i++)
{
MatrixInit (&stack->matrix[i*16]);
}
stack->size--;
}
void MatrixStackSetStackPosition (MatrixStack *stack, int pos)
{
stack->position += pos;
if (stack->position < 0)
stack->position = 0;
else if (stack->position > stack->size)
stack->position = stack->size;
}
void MatrixStackPushMatrix (MatrixStack *stack, float *ptr)
{
MatrixCopy (&stack->matrix[stack->position*16], ptr);
MatrixStackSetStackPosition (stack, 1);
}
float * MatrixStackPopMatrix (MatrixStack *stack, int size)
{
MatrixStackSetStackPosition(stack, -size);
return &stack->matrix[stack->position*16];
}
float * MatrixStackGetPos (MatrixStack *stack, int pos)
{
return &stack->matrix[pos*16];
}
float * MatrixStackGet (MatrixStack *stack)
{
return &stack->matrix[stack->position*16];
}
void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr)
{
MatrixCopy (&stack->matrix[pos*16], ptr);
}

View File

@ -0,0 +1,51 @@
/*
Copyright (C) 2006-2007 shash
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MATRIX_H
#define MATRIX_H
typedef struct MatrixStack
{
float *matrix;
int position;
int size;
} MatrixStack;
void MatrixInit (float *matrix);
void MatrixMultVec3x3 (float *matrix, float *vecPtr);
void MatrixMultVec4x4 (float *matrix, float *vecPtr);
void MatrixIdentity (float *matrix);
void MatrixMultiply (float *matrix, float *rightMatrix);
float MatrixGetMultipliedIndex(int index, float *matrix, float *rightMatrix);
void MatrixSet (float *matrix, int x, int y, float value);
void MatrixCopy (float *matrixDST, float *matrixSRC);
void MatrixTranslate (float *matrix, float *ptr);
void MatrixScale (float *matrix, float *ptr);
void MatrixStackInit (MatrixStack *stack);
void MatrixStackSetMaxSize (MatrixStack *stack, int size);
void MatrixStackSetStackPosition (MatrixStack *stack, int pos);
void MatrixStackPushMatrix (MatrixStack *stack, float *ptr);
float* MatrixStackPopMatrix (MatrixStack *stack, int size);
float* MatrixStackGetPos (MatrixStack *stack, int pos);
float* MatrixStackGet (MatrixStack *stack);
void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr);
#endif

View File

@ -0,0 +1,121 @@
/* Copyright (C) 2006 thoduv
Copyright (C) 2006-2007 Theo Berkau
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include "debug.h"
#include "types.h"
#include "mc.h"
#define FW_CMD_READ 0x3
#define FW_CMD_WRITEDISABLE 0x4
#define FW_CMD_READSTATUS 0x5
#define FW_CMD_WRITEENABLE 0x6
#define FW_CMD_PAGEWRITE 0xA
#define BM_CMD_AUTODETECT 0xFF
#define BM_CMD_WRITESTATUS 0x1
#define BM_CMD_WRITELOW 0x2
#define BM_CMD_READLOW 0x3
#define BM_CMD_WRITEDISABLE 0x4
#define BM_CMD_READSTATUS 0x5
#define BM_CMD_WRITEENABLE 0x6
#define BM_CMD_WRITEHIGH 0xA
#define BM_CMD_READHIGH 0xB
/* FLASH*/
#define COMM_PAGE_WRITE 0x0A
#define COMM_PAGE_ERASE 0xDB
#define COMM_SECTOR_ERASE 0xD8
#define COMM_CHIP_ERASE 0xC7
#define CARDFLASH_READ_BYTES_FAST 0x0B /* Not used*/
#define CARDFLASH_DEEP_POWDOWN 0xB9 /* Not used*/
#define CARDFLASH_WAKEUP 0xAB /* Not used*/
void mc_init(memory_chip_t *mc, int type)
{
mc->com = 0;
mc->addr = 0;
mc->addr_shift = 0;
mc->data = NULL;
mc->size = 0;
mc->write_enable = FALSE;
mc->writeable_buffer = FALSE;
mc->type = type;
mc->autodetectsize = 0;
switch(mc->type)
{
case MC_TYPE_EEPROM1:
mc->addr_size = 1;
break;
case MC_TYPE_EEPROM2:
case MC_TYPE_FRAM:
mc->addr_size = 2;
break;
case MC_TYPE_FLASH:
mc->addr_size = 3;
break;
default: break;
}
}
u8 *mc_alloc(memory_chip_t *mc, u32 size)
{
u8 *buffer;
buffer = malloc(size);
mc->data = buffer;
if(!buffer) { return NULL; }
mc->size = size;
mc->writeable_buffer = TRUE;
return buffer;
}
void mc_free(memory_chip_t *mc)
{
if(mc->data)
{
free(mc->data);
mc->data = 0;
}
mc_init(mc, 0);
}
void mc_realloc(memory_chip_t *mc, int type, u32 size)
{
mc_free(mc);
mc_init(mc, type);
mc_alloc(mc, size);
}
void mc_reset_com(memory_chip_t *mc)
{
}
u8 fw_transfer(memory_chip_t *mc, u8 data)
{
return 0;
}
u8 bm_transfer(memory_chip_t *mc, u8 data)
{
return 0;
}

View File

@ -0,0 +1,94 @@
/* Copyright (C) 2006 thoduv
Copyright (C) 2006 Theo Berkau
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __FW_H__
#define __FW_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include "types.h"
#define MC_TYPE_AUTODETECT 0x0
#define MC_TYPE_EEPROM1 0x1
#define MC_TYPE_EEPROM2 0x2
#define MC_TYPE_FLASH 0x3
#define MC_TYPE_FRAM 0x4
#define MC_SIZE_4KBITS 0x000200
#define MC_SIZE_64KBITS 0x002000
#define MC_SIZE_256KBITS 0x008000
#define MC_SIZE_512KBITS 0x010000
#define MC_SIZE_1MBITS 0x020000
#define MC_SIZE_2MBITS 0x040000
#define MC_SIZE_4MBITS 0x080000
#define MC_SIZE_8MBITS 0x100000
#define MC_SIZE_16MBITS 0x200000
#define MC_SIZE_64MBITS 0x800000
static int save_types[6][2] = {
{MC_TYPE_AUTODETECT,1},
{MC_TYPE_EEPROM1,MC_SIZE_4KBITS},
{MC_TYPE_EEPROM2,MC_SIZE_64KBITS},
{MC_TYPE_EEPROM2,MC_SIZE_512KBITS},
{MC_TYPE_FLASH,MC_SIZE_256KBITS},
{MC_TYPE_FRAM,MC_SIZE_2MBITS}
};
typedef struct
{
u8 com; /* persistent command actually handled */
u32 addr; /* current address for reading/writing */
u8 addr_shift; /* shift for address (since addresses are transfered by 3 bytes units) */
u8 addr_size; /* size of addr when writing/reading */
BOOL write_enable; /* is write enabled ? */
u8 *data; /* memory data */
u32 size; /* memory size */
BOOL writeable_buffer; /* is "data" writeable ? */
int type; /* type of Memory */
char *filename;
FILE *fp;
u8 autodetectbuf[32768];
int autodetectsize;
} memory_chip_t;
#define NDS_FW_SIZE_V1 (256 * 1024) /* size of fw memory on nds v1 */
#define NDS_FW_SIZE_V2 (512 * 1024) /* size of fw memory on nds v2 */
void mc_init(memory_chip_t *mc, int type); /* reset and init values for memory struct */
u8 *mc_alloc(memory_chip_t *mc, u32 size); /* alloc mc memory */
void mc_realloc(memory_chip_t *mc, int type, u32 size); /* realloc mc memory */
void mc_load_file(memory_chip_t *mc, const char* filename); /* load save file and setup fp */
int mc_load_duc(memory_chip_t *mc, const char* filename); /* load Action Replay DS save file */
void mc_free(memory_chip_t *mc); /* delete mc memory */
void mc_reset_com(memory_chip_t *mc); /* reset communication with mc */
u8 fw_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from firmware */
u8 bm_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from backup memory */
#ifdef __cplusplus
}
#endif
#endif /*__FW_H__*/

View File

@ -0,0 +1,141 @@
/* Copyright 2005-2006 Guillaume Duhamel
Copyright 2005 Theo Berkau
This file is part of Yabause.
Yabause is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Yabause is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Yabause; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MEM_H
#define MEM_H
#include <stdlib.h>
#include "types.h"
/* Type 1 Memory, faster for byte (8 bits) accesses */
static INLINE u8 T1ReadByte(u8 * mem, u32 addr)
{
return mem[addr];
}
static INLINE u16 T1ReadWord(u8 * mem, u32 addr)
{
#ifdef WORDS_BIGENDIAN
return (mem[addr + 1] << 8) | mem[addr];
#else
return *((u16 *) (mem + addr));
#endif
}
static INLINE u32 T1ReadLong(u8 * mem, u32 addr)
{
#ifdef WORDS_BIGENDIAN
return (mem[addr + 3] << 24 | mem[addr + 2] << 16 |
mem[addr + 1] << 8 | mem[addr]);
#else
return *((u32 *)mem + (addr>>2));
#endif
}
static INLINE u64 T1ReadQuad(u8 * mem, u32 addr)
{
#ifdef WORDS_BIGENDIAN
return (mem[addr + 7] << 56 | mem[addr + 6] << 48 |
mem[addr + 5] << 40 | mem[addr + 4] << 32 |
mem[addr + 3] << 24 | mem[addr + 2] << 16 |
mem[addr + 1] << 8 | mem[addr]);
#else
return *((u64 *) (mem + addr));
#endif
}
static INLINE void T1WriteByte(u8 * mem, u32 addr, u8 val)
{
mem[addr] = val;
}
static INLINE void T1WriteWord(u8 * mem, u32 addr, u16 val)
{
#ifdef WORDS_BIGENDIAN
mem[addr + 1] = val >> 8;
mem[addr] = val & 0xFF;
#else
*((u16 *) (mem + addr)) = val;
#endif
}
static INLINE void T1WriteLong(u8 * mem, u32 addr, u32 val)
{
#ifdef WORDS_BIGENDIAN
mem[addr + 3] = val >> 24;
mem[addr + 2] = (val >> 16) & 0xFF;
mem[addr + 1] = (val >> 8) & 0xFF;
mem[addr] = val & 0xFF;
#else
*((u32 *) (mem + addr)) = val;
#endif
}
/* Type 2 Memory, faster for word (16 bits) accesses */
static INLINE u8 T2ReadByte(u8 * mem, u32 addr)
{
#ifdef WORDS_BIGENDIAN
return mem[addr ^ 1];
#else
return mem[addr];
#endif
}
static INLINE u16 T2ReadWord(u8 * mem, u32 addr)
{
return *((u16 *) (mem + addr));
}
static INLINE u32 T2ReadLong(u8 * mem, u32 addr)
{
#ifdef WORDS_BIGENDIAN
return *((u16 *) (mem + addr + 2)) << 16 | *((u16 *) (mem + addr));
#else
return *((u32 *) (mem + addr));
#endif
}
static INLINE void T2WriteByte(u8 * mem, u32 addr, u8 val)
{
#ifdef WORDS_BIGENDIAN
mem[addr ^ 1] = val;
#else
mem[addr] = val;
#endif
}
static INLINE void T2WriteWord(u8 * mem, u32 addr, u16 val)
{
*((u16 *) (mem + addr)) = val;
}
static INLINE void T2WriteLong(u8 * mem, u32 addr, u32 val)
{
#ifdef WORDS_BIGENDIAN
*((u16 *) (mem + addr + 2)) = val >> 16;
*((u16 *) (mem + addr)) = val & 0xFFFF;
#else
*((u32 *) (mem + addr)) = val;
#endif
}
#endif

View File

@ -0,0 +1,333 @@
/* Copyright (C) 2006 Theo Berkau
Ideas borrowed from Stephane Dallongeville's SCSP core
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef REGISTERS_H
#define REGISTERS_H
#define REG_REGION_MASK 0x0FFFEF80
#define REG_BASE_DISPx 0x04000000
#define REG_BASE_DISPA 0x04000000
#define REG_BASE_DISPB 0x04001000
#define REG_BASE_DMA 0x04000080
#define REG_BASE_SIORTCTIMERS 0x04000100
#define REG_BASE_ROMIPC 0x04000180
#define REG_BASE_MEMIRQ 0x04000200
#define REG_BASE_MATH 0x04000280
#define REG_BASE_OTHER 0x04000300
#define REG_BASE_RCVPORTS 0x04100000
// Display Engine A
#define REG_DISPA_DISPCNT 0x04000000
#define REG_DISPA_VCOUNT 0x04000006
#define REG_DISPA_BG0CNT 0x04000008
#define REG_DISPA_BG1CNT 0x0400000A
#define REG_DISPA_BG2CNT 0x0400000C
#define REG_DISPA_BG3CNT 0x0400000E
#define REG_DISPA_BG0HOFS 0x04000010
#define REG_DISPA_BG0VOFS 0x04000012
#define REG_DISPA_BG1HOFS 0x04000014
#define REG_DISPA_BG1VOFS 0x04000016
#define REG_DISPA_BG2HOFS 0x04000018
#define REG_DISPA_BG2VOFS 0x0400001A
#define REG_DISPA_BG3HOFS 0x0400001C
#define REG_DISPA_BG3VOFS 0x0400001E
#define REG_DISPA_BG2PA 0x04000020
#define REG_DISPA_BG2PB 0x04000022
#define REG_DISPA_BG2PC 0x04000024
#define REG_DISPA_BG2PD 0x04000026
#define REG_DISPA_BG2XL 0x04000028
#define REG_DISPA_BG2XH 0x0400002A
#define REG_DISPA_BG2YL 0x0400002C
#define REG_DISPA_BG2YH 0x0400002E
#define REG_DISPA_BG3PA 0x04000030
#define REG_DISPA_BG3PB 0x04000032
#define REG_DISPA_BG3PC 0x04000034
#define REG_DISPA_BG3PD 0x04000036
#define REG_DISPA_BG3XL 0x04000038
#define REG_DISPA_BG3XH 0x0400003A
#define REG_DISPA_BG3YL 0x0400003C
#define REG_DISPA_BG3YH 0x0400003E
#define REG_DISPA_WIN0H 0x04000040
#define REG_DISPA_WIN1H 0x04000042
#define REG_DISPA_WIN0V 0x04000044
#define REG_DISPA_WIN1V 0x04000046
#define REG_DISPA_WININ 0x04000048
#define REG_DISPA_WINOUT 0x0400004A
#define REG_DISPA_MOSAIC 0x0400004C
#define REG_DISPA_BLDCNT 0x04000050
#define REG_DISPA_BLDALPHA 0x04000052
#define REG_DISPA_BLDY 0x04000054
#define REG_DISPA_MASTERBRIGHT 0x0400006C
// DMA
#define REG_DMA0SAD 0x040000B0
#define REG_DMA0DAD 0x040000B4
#define REG_DMA0CNTL 0x040000B8
#define REG_DMA0CNTH 0x040000BA
#define REG_DMA1SAD 0x040000BC
#define REG_DMA1DAD 0x040000C0
#define REG_DMA1CNTL 0x040000C4
#define REG_DMA1CNTH 0x040000C6
#define REG_DMA2SAD 0x040000C8
#define REG_DMA2DAD 0x040000CC
#define REG_DMA2CNTL 0x040000D0
#define REG_DMA2CNTH 0x040000D2
#define REG_DMA3SAD 0x040000D4
#define REG_DMA3DAD 0x040000D8
#define REG_DMA3CNTL 0x040000DC
#define REG_DMA3CNTH 0x040000DE
#define REG_DMA0FILL 0x040000E0
#define REG_DMA1FILL 0x040000E4
#define REG_DMA2FILL 0x040000E8
#define REG_DMA3FILL 0x040000EC
// Timers
#define REG_TM0CNTL 0x04000100
#define REG_TM0CNTH 0x04000102
#define REG_TM1CNTL 0x04000104
#define REG_TM1CNTH 0x04000106
#define REG_TM2CNTL 0x04000108
#define REG_TM2CNTH 0x0400010A
#define REG_TM3CNTL 0x0400010C
#define REG_TM3CNTH 0x0400010E
// SIO/Keypad Input/RTC
#define REG_SIODATA32 0x04000120
#define REG_SIOCNT 0x04000128
#define REG_KEYINPUT 0x04000130
#define REG_KEYCNT 0x04000132
#define REG_RCNT 0x04000134
#define REG_EXTKEYIN 0x04000136
#define REG_RTC 0x04000138
// IPC
#define REG_IPCSYNC 0x04000180
#define REG_IPCFIFOCNT 0x04000184
#define REG_IPCFIFOSEND 0x04000188
// ROM
#define REG_AUXSPICNT 0x040001A0
#define REG_AUXSPIDATA 0x040001A2
#define REG_GCROMCTRL 0x040001A4
#define REG_GCCMDOUT 0x040001A8
#define REG_ENCSEED0L 0x040001B0
#define REG_ENCSEED1L 0x040001B4
#define REG_ENCSEED0H 0x040001B8
#define REG_ENCSEED1H 0x040001BC
#define REG_SPICNT 0x040001C0
#define REG_SPIDATA 0x040001C2
// Memory/IRQ
#define REG_EXMEMCNT 0x04000204
#define REG_WIFIWAITCNT 0x04000206
#define REG_IME 0x04000208
#define REG_IE 0x04000210
#define REG_IF 0x04000214
#define REG_VRAMCNTA 0x04000240
#define REG_VRAMSTAT 0x04000240
#define REG_VRAMCNTB 0x04000241
#define REG_WRAMSTAT 0x04000241
#define REG_VRAMCNTC 0x04000242
#define REG_VRAMCNTD 0x04000243
#define REG_VRAMCNTE 0x04000244
#define REG_VRAMCNTF 0x04000245
#define REG_VRAMCNTG 0x04000246
#define REG_WRAMCNT 0x04000247
#define REG_VRAMCNTH 0x04000248
#define REG_VRAMCNTI 0x04000249
// Math
#define REG_DIVCNT 0x04000280
#define REG_DIVNUMER 0x04000290
#define REG_DIVDENOM 0x04000298
#define REG_DIVRESULT 0x040002A0
#define REG_DIVREMRESULT 0x040002A8
#define REG_SQRTCNT 0x040002B0
#define REG_SQRTRESULT 0x040002B4
#define REG_SQRTPARAM 0x040002B8
// Other
#define REG_POSTFLG 0x04000300
#define REG_HALTCNT 0x04000301
#define REG_POWCNT1 0x04000304
#define REG_POWCNT2 0x04000304
#define REG_BIOSPROT 0x04000308
#define REG_DISPB_DISPCNT 0x04001000
#define REG_DISPB_BG0CNT 0x04001008
#define REG_DISPB_BG1CNT 0x0400100A
#define REG_DISPB_BG2CNT 0x0400100C
#define REG_DISPB_BG3CNT 0x0400100E
#define REG_DISPB_BG0HOFS 0x04001010
#define REG_DISPB_BG0VOFS 0x04001012
#define REG_DISPB_BG1HOFS 0x04001014
#define REG_DISPB_BG1VOFS 0x04001016
#define REG_DISPB_BG2HOFS 0x04001018
#define REG_DISPB_BG2VOFS 0x0400101A
#define REG_DISPB_BG3HOFS 0x0400101C
#define REG_DISPB_BG3VOFS 0x0400101E
#define REG_DISPB_BG2PA 0x04001020
#define REG_DISPB_BG2PB 0x04001022
#define REG_DISPB_BG2PC 0x04001024
#define REG_DISPB_BG2PD 0x04001026
#define REG_DISPB_BG2XL 0x04001028
#define REG_DISPB_BG2XH 0x0400102A
#define REG_DISPB_BG2YL 0x0400102C
#define REG_DISPB_BG2YH 0x0400102E
#define REG_DISPB_BG3PA 0x04001030
#define REG_DISPB_BG3PB 0x04001032
#define REG_DISPB_BG3PC 0x04001034
#define REG_DISPB_BG3PD 0x04001036
#define REG_DISPB_BG3XL 0x04001038
#define REG_DISPB_BG3XH 0x0400103A
#define REG_DISPB_BG3YL 0x0400103C
#define REG_DISPB_BG3YH 0x0400103E
#define REG_DISPB_WIN0H 0x04001040
#define REG_DISPB_WIN1H 0x04001042
#define REG_DISPB_WIN0V 0x04001044
#define REG_DISPB_WIN1V 0x04001046
#define REG_DISPB_WININ 0x04001048
#define REG_DISPB_WINOUT 0x0400104A
#define REG_DISPB_MOSAIC 0x0400104C
#define REG_DISPB_BLDCNT 0x04001050
#define REG_DISPB_BLDALPHA 0x04001052
#define REG_DISPB_BLDY 0x04001054
#define REG_DISPB_MASTERBRIGHT 0x0400106C
// Receive ports
#define REG_IPCFIFORECV 0x04100000
#define REG_GCDATAIN 0x04100010
#define REG_DISPB 0x00001000
// core A and B specific
#define REG_DISPx_DISPCNT 0x04000000
#define REG_DISPx_VCOUNT 0x04000006
#define REG_DISPx_BG0CNT 0x04000008
#define REG_DISPx_BG1CNT 0x0400000A
#define REG_DISPx_BG2CNT 0x0400000C
#define REG_DISPx_BG3CNT 0x0400000E
#define REG_DISPx_BG0HOFS 0x04000010
#define REG_DISPx_BG0VOFS 0x04000012
#define REG_DISPx_BG1HOFS 0x04000014
#define REG_DISPx_BG1VOFS 0x04000016
#define REG_DISPx_BG2HOFS 0x04000018
#define REG_DISPx_BG2VOFS 0x0400001A
#define REG_DISPx_BG3HOFS 0x0400001C
#define REG_DISPx_BG3VOFS 0x0400001E
#define REG_DISPx_BG2PA 0x04000020
#define REG_DISPx_BG2PB 0x04000022
#define REG_DISPx_BG2PC 0x04000024
#define REG_DISPx_BG2PD 0x04000026
#define REG_DISPx_BG2XL 0x04000028
#define REG_DISPx_BG2XH 0x0400002A
#define REG_DISPx_BG2YL 0x0400002C
#define REG_DISPx_BG2YH 0x0400002E
#define REG_DISPx_BG3PA 0x04000030
#define REG_DISPx_BG3PB 0x04000032
#define REG_DISPx_BG3PC 0x04000034
#define REG_DISPx_BG3PD 0x04000036
#define REG_DISPx_BG3XL 0x04000038
#define REG_DISPx_BG3XH 0x0400003A
#define REG_DISPx_BG3YL 0x0400003C
#define REG_DISPx_BG3YH 0x0400003E
#define REG_DISPx_WIN0H 0x04000040
#define REG_DISPx_WIN1H 0x04000042
#define REG_DISPx_WIN0V 0x04000044
#define REG_DISPx_WIN1V 0x04000046
#define REG_DISPx_WININ 0x04000048
#define REG_DISPx_WINOUT 0x0400004A
#define REG_DISPx_MOSAIC 0x0400004C
#define REG_DISPx_BLDCNT 0x04000050
#define REG_DISPx_BLDALPHA 0x04000052
#define REG_DISPx_BLDY 0x04000054
#define REG_DISPx_MASTERBRIGHT 0x0400006C
// core A specific
#define REG_DISPA_DISPSTAT 0x04000004
#define REG_DISPA_DISP3DCNT 0x04000060
#define REG_DISPA_DISPCAPCNT 0x04000064
#define REG_DISPA_DISPMMEMFIFO 0x04000068
#define eng_3D_RDLINES_COUNT 0x04000320
#define eng_3D_EDGE_COLOR 0x04000330
#define eng_3D_ALPHA_TEST_REF 0x04000340
#define eng_3D_CLEAR_COLOR 0x04000350
#define eng_3D_CLEAR_DEPTH 0x04000354
#define eng_3D_CLRIMAGE_OFFSET 0x04000356
#define eng_3D_FOG_COLOR 0x04000358
#define eng_3D_FOG_OFFSET 0x0400035C
#define eng_3D_FOG_TABLE 0x04000360
#define eng_3D_TOON_TABLE 0x04000380
#define eng_3D_GXFIFO 0x04000400
// 3d commands
#define cmd_3D_MTX_MODE 0x04000440
#define cmd_3D_MTX_PUSH 0x04000444
#define cmd_3D_MTX_POP 0x04000448
#define cmd_3D_MTX_STORE 0x0400044C
#define cmd_3D_MTX_RESTORE 0x04000450
#define cmd_3D_MTX_IDENTITY 0x04000454
#define cmd_3D_MTX_LOAD_4x4 0x04000458
#define cmd_3D_MTX_LOAD_4x3 0x0400045C
#define cmd_3D_MTX_MULT_4x4 0x04000460
#define cmd_3D_MTX_MULT_4x3 0x04000464
#define cmd_3D_MTX_MULT_3x3 0x04000468
#define cmd_3D_MTX_SCALE 0x0400046C
#define cmd_3D_MTX_TRANS 0x04000470
#define cmd_3D_COLOR 0x04000480
#define cmd_3D_NORMA 0x04000484
#define cmd_3D_TEXCOORD 0x04000488
#define cmd_3D_VTX_16 0x0400048C
#define cmd_3D_VTX_10 0x04000490
#define cmd_3D_VTX_XY 0x04000494
#define cmd_3D_VTX_XZ 0x04000498
#define cmd_3D_VTX_YZ 0x0400049C
#define cmd_3D_VTX_DIFF 0x040004A0
#define cmd_3D_POLYGON_ATTR 0x040004A4
#define cmd_3D_TEXIMAGE_PARAM 0x040004A8
#define cmd_3D_PLTT_BASE 0x040004AC
#define cmd_3D_DIF_AMB 0x040004C0
#define cmd_3D_SPE_EMI 0x040004C4
#define cmd_3D_LIGHT_VECTOR 0x040004C8
#define cmd_3D_LIGHT_COLOR 0x040004CC
#define cmd_3D_SHININESS 0x040004D0
#define cmd_3D_BEGIN_VTXS 0x04000500
#define cmd_3D_END_VTXS 0x04000504
#define cmd_3D_SWAP_BUFFERS 0x04000540
#define cmd_3D_VIEWPORT 0x04000580
#define cmd_3D_BOX_TEST 0x040005C0
#define cmd_3D_POS_TEST 0x040005C4
#define cmd_3D_VEC_TEST 0x040005C8
#define eng_3D_GXSTAT 0x04000600
#define eng_3D_RAM_COUNT 0x04000604
#define eng_3D_DISP_1DOT_DEPTH 0x04000610
#define eng_3D_POS_RESULT 0x04000620
#define eng_3D_VEC_RESULT 0x04000630
#define eng_3D_CLIPMTX_RESULT 0x04000640
#define eng_3D_VECMTX_RESULT 0x04000680
#endif

View File

@ -0,0 +1,30 @@
#ifndef _SPU_EXPORTS_H
#define _SPU_EXPORTS_H
#ifndef _SPU_CPP_
void SPU_WriteLong(u32 addr, u32 val);
void SPU_WriteByte(u32 addr, u8 val);
void SPU_WriteWord(u32 addr, u16 val);
void SPU_EmulateSamples(int numsamples);
int SPU_ChangeSoundCore(int coreid, int buffersize);
void SPU_Reset(void);
void SPU_DeInit(void);
typedef struct
{
int id;
const char *Name;
int (*Init)(int buffersize);
void (*DeInit)();
void (*UpdateAudio)(s16 *buffer, u32 num_samples);
u32 (*GetAudioSpace)();
void (*MuteAudio)();
void (*UnMuteAudio)();
void (*SetVolume)(int volume);
} SoundInterface_struct;
#endif _SPU_CPP_
#endif //_SPU_EXPORTS_H

View File

@ -0,0 +1,944 @@
/*
Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
Code added on 18/08/2006 by shash
- Missing missaligned addresses correction
(reference in http://nocash.emubase.de/gbatek.htm#cpumemoryalignments)
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "bios.h"
#include "debug.h"
#include "MMU.h"
#define REG_NUM(i, n) (((i)>>n)&0x7)
extern BOOL execute;
// Use this macros for reading/writing, so the GDB stub isn't broken
#ifdef GDB_STUB
#define READ32(a,b) cpu->mem_if->read32(a,b)
#define WRITE32(a,b,c) cpu->mem_if->write32(a,b,c)
#define READ16(a,b) cpu->mem_if->read16(a,b)
#define WRITE16(a,b,c) cpu->mem_if->write16(a,b,c)
#define READ8(a,b) cpu->mem_if->read8(a,b)
#define WRITE8(a,b,c) cpu->mem_if->write8(a,b,c)
#else
#define READ32(a,b) MMU_read32(cpu->proc_ID, b)
#define WRITE32(a,b,c) MMU_write32(cpu->proc_ID,b,c)
#define READ16(a,b) MMU_read16(cpu->proc_ID, b)
#define WRITE16(a,b,c) MMU_write16(cpu->proc_ID,b,c)
#define READ8(a,b) MMU_read8(cpu->proc_ID, b)
#define WRITE8(a,b,c) MMU_write8(cpu->proc_ID,b,c)
#endif
static u32 FASTCALL OP_UND_THUMB(armcpu_t *cpu)
{
execute = FALSE;
return 1;
}
static u32 FASTCALL OP_LSL_0(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)];
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 2;
}
static u32 FASTCALL OP_LSL(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 v = (i>>6) & 0x1F;
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], 32-v);
cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] << v);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 2;
}
static u32 FASTCALL OP_LSR_0(armcpu_t *cpu)
{
u32 i = cpu->instruction;
// cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]);
cpu->R[REG_NUM(i, 0)] = 0;
cpu->CPSR.bits.N = 0;
cpu->CPSR.bits.Z = 1;
return 2;
}
static u32 FASTCALL OP_LSR(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 v = (i>>6) & 0x1F;
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] >> v);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 2;
}
static u32 FASTCALL OP_ASR_0(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]);
cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 3)])*0xFFFFFFFF;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 2;
}
static u32 FASTCALL OP_ASR(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 v = (i>>6) & 0x1F;
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1);
cpu->R[REG_NUM(i, 0)] = (((s32)cpu->R[REG_NUM(i, 3)]) >> v);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 2;
}
static u32 FASTCALL OP_ADD_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 a = cpu->R[REG_NUM(i, 3)];
u32 b = cpu->R[REG_NUM(i, 6)];
cpu->R[REG_NUM(i, 0)] = a + b;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
return 3;
}
static u32 FASTCALL OP_SUB_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 a = cpu->R[REG_NUM(i, 3)];
u32 b = cpu->R[REG_NUM(i, 6)];
cpu->R[REG_NUM(i, 0)] = a - b;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
return 3;
}
static u32 FASTCALL OP_ADD_IMM3(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 a = cpu->R[REG_NUM(i, 3)];
cpu->R[REG_NUM(i, 0)] = a + REG_NUM(i, 6);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
return 2;
}
static u32 FASTCALL OP_SUB_IMM3(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 a = cpu->R[REG_NUM(i, 3)];
cpu->R[REG_NUM(i, 0)] = a - REG_NUM(i, 6);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
return 2;
}
static u32 FASTCALL OP_MOV_IMM8(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 8)] = i & 0xFF;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 8)] == 0;
return 2;
}
static u32 FASTCALL OP_CMP_IMM8(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF);
cpu->CPSR.bits.N = BIT31(tmp);
cpu->CPSR.bits.Z = tmp == 0;
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
return 2;
}
static u32 FASTCALL OP_ADD_IMM8(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 tmp = cpu->R[REG_NUM(i, 8)] + (i & 0xFF);
cpu->CPSR.bits.N = BIT31(tmp);
cpu->CPSR.bits.Z = tmp == 0;
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
cpu->R[REG_NUM(i, 8)] = tmp;
return 2;
}
static u32 FASTCALL OP_SUB_IMM8(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF);
cpu->CPSR.bits.N = BIT31(tmp);
cpu->CPSR.bits.Z = tmp == 0;
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
cpu->R[REG_NUM(i, 8)] = tmp;
return 2;
}
static u32 FASTCALL OP_AND(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 0)] &= cpu->R[REG_NUM(i, 3)];
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
static u32 FASTCALL OP_EOR(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 0)] ^= cpu->R[REG_NUM(i, 3)];
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
static u32 FASTCALL OP_LSL_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
if(!v)
{
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
if(v<32)
{
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], 32-v);
cpu->R[REG_NUM(i, 0)] <<= v;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
if(v==32)
cpu->CPSR.bits.C = BIT0(cpu->R[REG_NUM(i, 0)]);
else
cpu->CPSR.bits.C = 0;
cpu->R[REG_NUM(i, 0)] = 0;
cpu->CPSR.bits.N = 0;
cpu->CPSR.bits.Z = 1;
return 3;
}
static u32 FASTCALL OP_LSR_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
if(!v)
{
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
if(v<32)
{
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
cpu->R[REG_NUM(i, 0)] >>= v;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
if(v==32)
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
else
cpu->CPSR.bits.C = 0;
cpu->R[REG_NUM(i, 0)] = 0;
cpu->CPSR.bits.N = 0;
cpu->CPSR.bits.Z = 1;
return 3;
}
static u32 FASTCALL OP_ASR_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
if(!v)
{
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
if(v<32)
{
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 0)]) >> v);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 0)])*0xFFFFFFFF;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
static u32 FASTCALL OP_ADC_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 a = cpu->R[REG_NUM(i, 0)];
u32 b = cpu->R[REG_NUM(i, 3)];
u32 tmp = b + cpu->CPSR.bits.C;
u32 res = a + tmp;
cpu->R[REG_NUM(i, 0)] = res;
cpu->CPSR.bits.N = BIT31(res);
cpu->CPSR.bits.Z = res == 0;
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res);
cpu->CPSR.bits.V = SIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, a, res);
return 3;
}
static u32 FASTCALL OP_SBC_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 a = cpu->R[REG_NUM(i, 0)];
u32 b = cpu->R[REG_NUM(i, 3)];
u32 tmp = a - (!cpu->CPSR.bits.C);
u32 res = tmp - b;
cpu->R[REG_NUM(i, 0)] = res;
cpu->CPSR.bits.N = BIT31(res);
cpu->CPSR.bits.Z = res == 0;
cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp)) & (!UNSIGNED_OVERFLOW(tmp, b, res));
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, b, res);
return 3;
}
static u32 FASTCALL OP_ROR_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
if(v == 0)
{
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
v &= 0xF;
if(v == 0)
{
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
cpu->R[REG_NUM(i, 0)] = ROR(cpu->R[REG_NUM(i, 0)], v);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
static u32 FASTCALL OP_TST(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 tmp = cpu->R[REG_NUM(i, 0)] & cpu->R[REG_NUM(i, 3)];
cpu->CPSR.bits.N = BIT31(tmp);
cpu->CPSR.bits.Z = tmp == 0;
return 3;
}
static u32 FASTCALL OP_NEG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 a = cpu->R[REG_NUM(i, 3)];
cpu->R[REG_NUM(i, 0)] = -((signed int)a);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]);
return 3;
}
static u32 FASTCALL OP_CMP(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 tmp = cpu->R[REG_NUM(i, 0)] -cpu->R[REG_NUM(i, 3)];
cpu->CPSR.bits.N = BIT31(tmp);
cpu->CPSR.bits.Z = tmp == 0;
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
return 3;
}
static u32 FASTCALL OP_CMN(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 tmp = cpu->R[REG_NUM(i, 0)] + cpu->R[REG_NUM(i, 3)];
//execute = FALSE;
//log::ajouter("OP_CMN THUMB");
cpu->CPSR.bits.N = BIT31(tmp);
cpu->CPSR.bits.Z = tmp == 0;
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
return 3;
}
static u32 FASTCALL OP_ORR(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 0)] |= cpu->R[REG_NUM(i, 3)];
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
static u32 FASTCALL OP_MUL_REG(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 0)] *= cpu->R[REG_NUM(i, 3)];
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
static u32 FASTCALL OP_BIC(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 0)] &= (~cpu->R[REG_NUM(i, 3)]);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
static u32 FASTCALL OP_MVN(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 0)] = (~cpu->R[REG_NUM(i, 3)]);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
return 3;
}
static u32 FASTCALL OP_ADD_SPE(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 Rd = (i&7) | ((i>>4)&8);
cpu->R[Rd] += cpu->R[REG_POS(i, 3)];
if(Rd==15)
cpu->next_instruction = cpu->R[15];
return 2;
}
static u32 FASTCALL OP_CMP_SPE(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 Rn = (i&7) | ((i>>4)&8);
u32 tmp = cpu->R[Rn] -cpu->R[REG_POS(i, 3)];
cpu->CPSR.bits.N = BIT31(tmp);
cpu->CPSR.bits.Z = tmp == 0;
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp);
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp);
return 3;
}
static u32 FASTCALL OP_MOV_SPE(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 Rd = (i&7) | ((i>>4)&8);
cpu->R[Rd] = cpu->R[REG_POS(i, 3)];
if(Rd==15)
cpu->next_instruction = cpu->R[15];
return 2;
}
static u32 FASTCALL OP_BX_THUMB(armcpu_t *cpu)
{
u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)];
cpu->CPSR.bits.T = BIT0(Rm);
cpu->R[15] = (Rm & 0xFFFFFFFE);
cpu->next_instruction = cpu->R[15];
return 3;
}
static u32 FASTCALL OP_BLX_THUMB(armcpu_t *cpu)
{
u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)];
cpu->CPSR.bits.T = BIT0(Rm);
cpu->R[14] = cpu->next_instruction | 1;
cpu->R[15] = (Rm & 0xFFFFFFFE);
cpu->next_instruction = cpu->R[15];
return 3;
}
static u32 FASTCALL OP_LDR_PCREL(armcpu_t *cpu)
{
u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((cpu->instruction&0xFF)<<2);
cpu->R[REG_NUM(cpu->instruction, 8)] = READ32(cpu->mem_if->data, adr);
return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_STR_REG_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 6)] + cpu->R[REG_NUM(i, 3)];
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]);
return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_STRH_REG_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
WRITE16(cpu->mem_if->data, adr, ((u16)cpu->R[REG_NUM(i, 0)]));
return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_STRB_REG_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
WRITE8(cpu->mem_if->data, adr, ((u8)cpu->R[REG_NUM(i, 0)]));
return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDRSB_REG_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
cpu->R[REG_NUM(i, 0)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDR_REG_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = (cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]);
u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC);
adr = (adr&3)*8;
tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
cpu->R[REG_NUM(i, 0)] = tempValue;
return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDRH_REG_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr);
return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDRB_REG_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr);
return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDRSH_REG_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
cpu->R[REG_NUM(i, 0)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_STR_IMM_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C);
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]);
return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDR_IMM_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C);
u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC);
adr = (adr&3)*8;
tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
cpu->R[REG_NUM(i, 0)] = tempValue;
return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_STRB_IMM_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F);
WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]);
return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDRB_IMM_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F);
cpu->R[REG_NUM(i, 0)] = READ8(cpu->mem_if->data, adr);
return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_STRH_IMM_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E);
WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_NUM(i, 0)]);
return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDRH_IMM_OFF(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E);
cpu->R[REG_NUM(i, 0)] = READ16(cpu->mem_if->data, adr);
return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_STR_SPREL(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[13] + ((i&0xFF)<<2);
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 8)]);
return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_LDR_SPREL(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[13] + ((i&0xFF)<<2);
cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr);
return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
}
static u32 FASTCALL OP_ADD_2PC(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 8)] = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2);
return 5;
}
static u32 FASTCALL OP_ADD_2SP(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2);
return 2;
}
static u32 FASTCALL OP_ADJUST_P_SP(armcpu_t *cpu)
{
cpu->R[13] += ((cpu->instruction&0x7F)<<2);
return 1;
}
static u32 FASTCALL OP_ADJUST_M_SP(armcpu_t *cpu)
{
cpu->R[13] -= ((cpu->instruction&0x7F)<<2);
return 1;
}
static u32 FASTCALL OP_PUSH(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[13] - 4;
u32 c = 0, j;
for(j = 0; j<8; ++j)
if(BIT_N(i, 7-j))
{
WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]);
c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
adr -= 4;
}
cpu->R[13] = adr + 4;
return c + 3;
}
static u32 FASTCALL OP_PUSH_LR(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[13] - 4;
u32 c = 0, j;
WRITE32(cpu->mem_if->data, adr, cpu->R[14]);
c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
adr -= 4;
for(j = 0; j<8; ++j)
if(BIT_N(i, 7-j))
{
WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]);
c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
adr -= 4;
}
cpu->R[13] = adr + 4;
return c + 4;
}
static u32 FASTCALL OP_POP(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[13];
u32 c = 0, j;
for(j = 0; j<8; ++j)
if(BIT_N(i, j))
{
cpu->R[j] = READ32(cpu->mem_if->data, adr);
c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
adr += 4;
}
cpu->R[13] = adr;
return c + 2;
}
static u32 FASTCALL OP_POP_PC(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[13];
u32 c = 0, j;
u32 v;
for(j = 0; j<8; ++j)
if(BIT_N(i, j))
{
cpu->R[j] = READ32(cpu->mem_if->data, adr);
c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
adr += 4;
}
v = READ32(cpu->mem_if->data, adr);
c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
cpu->R[15] = v & 0xFFFFFFFE;
cpu->next_instruction = v & 0xFFFFFFFE;
if(cpu->proc_ID==0)
cpu->CPSR.bits.T = BIT0(v);
adr += 4;
cpu->R[13] = adr;
return c + 5;
}
static u32 FASTCALL OP_BKPT_THUMB(armcpu_t *cpu)
{
return 1;
}
static u32 FASTCALL OP_STMIA_THUMB(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 8)];
u32 c = 0, j;
for(j = 0; j<8; ++j)
if(BIT_N(i, j))
{
WRITE32(cpu->mem_if->data, adr, cpu->R[j]);
c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
adr += 4;
}
cpu->R[REG_NUM(i, 8)] = adr;
return c + 2;
}
static u32 FASTCALL OP_LDMIA_THUMB(armcpu_t *cpu)
{
u32 i = cpu->instruction;
u32 adr = cpu->R[REG_NUM(i, 8)];
u32 c = 0, j;
for(j = 0; j<8; ++j)
if(BIT_N(i, j))
{
cpu->R[j] = READ32(cpu->mem_if->data, adr);
c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
adr += 4;
}
cpu->R[REG_NUM(i, 8)] = adr;
return c + 3;
}
static u32 FASTCALL OP_B_COND(armcpu_t *cpu)
{
u32 i = cpu->instruction;
if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR))
return 1;
cpu->R[15] += ((s32)((s8)(i&0xFF)))<<1;
cpu->next_instruction = cpu->R[15];
return 3;
}
static u32 FASTCALL OP_SWI_THUMB(armcpu_t *cpu)
{
if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
{
/* we use an irq thats not in the irq tab, as
it was replaced duie to a changed intVector */
Status_Reg tmp = cpu->CPSR;
armcpu_switchMode(cpu, SVC); /* enter svc mode */
cpu->R[14] = cpu->R[15] - 4; /* jump to swi Vector */
cpu->SPSR = tmp; /* save old CPSR as new SPSR */
cpu->CPSR.bits.T = 0; /* handle as ARM32 code */
cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */
cpu->R[15] = cpu->intVector + 0x08;
cpu->next_instruction = cpu->R[15];
return 3;
}
else
{
u32 swinum = cpu->instruction & 0xFF;
return cpu->swi_tab[swinum](cpu) + 3;
}
//return 3;
}
#define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800))
static u32 FASTCALL OP_B_UNCOND(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[15] += (SIGNEEXT_IMM11(i)<<1);
cpu->next_instruction = cpu->R[15];
return 3;
}
static u32 FASTCALL OP_BLX(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1))&0xFFFFFFFC;
cpu->R[14] = cpu->next_instruction | 1;
cpu->next_instruction = cpu->R[15];
cpu->CPSR.bits.T = 0;
return 3;
}
static u32 FASTCALL OP_BL_10(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[14] = cpu->R[15] + (SIGNEEXT_IMM11(i)<<12);
return 1;
}
static u32 FASTCALL OP_BL_THUMB(armcpu_t *cpu)
{
u32 i = cpu->instruction;
cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1));
cpu->R[14] = cpu->next_instruction | 1;
cpu->next_instruction = cpu->R[15];
return 3;
}
#define TYPE_RETOUR u32
#define CALLTYPE FASTCALL
#define PARAMETRES armcpu_t *cpu
#define NOM_THUMB_TAB thumb_instructions_set
#include "thumb_tabdef.inc"

View File

@ -0,0 +1,30 @@
/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef THUMB_INSTRUCTIONS_H
#define THUMB_INSTRUCTIONS_H
#include "armcpu.h"
extern u32 (FASTCALL* thumb_instructions_set[1024])(armcpu_t * cpu);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
/* Copyright (C) 2005 Guillaume Duhamel
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef TYPES_HPP
#define TYPES_HPP
#ifndef FASTCALL
#ifdef __MINGW32__
#define FASTCALL __attribute__((fastcall))
#elif defined (__i386__)
#define FASTCALL __attribute__((regparm(3)))
#else
#define FASTCALL
#endif
#endif
#ifndef INLINE
#ifdef _MSC_VER
#define INLINE _inline
#else
#define INLINE inline
#endif
#endif
#ifdef DESMUME_COCOA
#ifdef __BIG_ENDIAN__
#define WORDS_BIGENDIAN
#endif
#endif
#if defined(__LP64__)
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long u64;
typedef unsigned long pointer;
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long s64;
#else
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
#ifdef _MSC_VER
typedef unsigned __int64 u64;
#else
typedef unsigned long long u64;
#endif
typedef unsigned long pointer;
typedef signed char s8;
typedef signed short s16;
typedef signed long s32;
#ifdef _MSC_VER
typedef __int64 s64;
#else
typedef signed long long s64;
#endif
#endif
typedef u8 uint8;
typedef u16 uint16;
#ifndef OBJ_C
typedef u32 uint32;
#else
#define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts
#endif
/*---------- GPU3D fixed-points types -----------*/
typedef s32 f32;
#define inttof32(n) ((n) << 12)
#define f32toint(n) ((n) >> 12)
#define floattof32(n) ((int32)((n) * (1 << 12)))
#define f32tofloat(n) (((float)(n)) / (float)(1<<12))
typedef s16 t16;
#define f32tot16(n) ((t16)(n >> 8))
#define inttot16(n) ((n) << 4)
#define t16toint(n) ((n) >> 4)
#define floattot16(n) ((t16)((n) * (1 << 4)))
#define t16ofloat(n) (((float)(n)) / (float)(1<<4))
typedef s16 v16;
#define inttov16(n) ((n) << 12)
#define f32tov16(n) (n)
#define floattov16(n) ((v16)((n) * (1 << 12)))
#define v16toint(n) ((n) >> 12)
#define v16tofloat(n) (((float)(n)) / (float)(1<<12))
typedef s16 v10;
#define inttov10(n) ((n) << 9)
#define f32tov10(n) ((v10)(n >> 3))
#define v10toint(n) ((n) >> 9)
#define floattov10(n) ((v10)((n) * (1 << 9)))
#define v10tofloat(n) (((float)(n)) / (float)(1<<9))
/*----------------------*/
#ifndef OBJ_C
typedef int BOOL;
#else
//apple also defines BOOL
typedef int desmume_BOOL;
#define BOOL desmume_BOOL
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifdef __GNUC__
#define PACKED __attribute__((packed))
#endif
#ifdef WORDS_BIGENDIAN
# define LOCAL_BE
#else
# define LOCAL_LE
#endif
/* little endian (ds' endianess) to local endianess convert macros */
#ifdef LOCAL_BE /* local arch is big endian */
# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
#else /* local arch is little endian */
# define LE_TO_LOCAL_16(x) (x)
# define LE_TO_LOCAL_32(x) (x)
# define LOCAL_TO_LE_16(x) (x)
# define LOCAL_TO_LE_32(x) (x)
#endif
/* kilobytes and megabytes macro */
#define MB(x) ((x)*1024*1024)
#define KB(x) ((x)*1024)
#define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7")
typedef enum
{
ARM9 = 0,
ARM7 = 1
} cpu_id_t;
#define __PACKED __attribute__((__packed__))
#endif

View File

@ -0,0 +1,856 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "desmume/MMU.h"
#include "desmume/armcpu.h"
#include "desmume/ndssystem.h"
#include "desmume/spu_exports.h"
#include "desmume/cp15.h"
#include "zlib/zlib.h"
#include "../xsfc/tagget.h"
#include "../xsfc/drvimpl.h"
volatile BOOL execute = FALSE;
static struct
{
unsigned char *rom;
unsigned char *state;
unsigned romsize;
unsigned statesize;
unsigned stateptr;
} loaderwork = { 0, 0, 0, 0, 0 };
static void load_term(void)
{
if (loaderwork.rom)
{
free(loaderwork.rom);
loaderwork.rom = 0;
}
loaderwork.romsize = 0;
if (loaderwork.state)
{
free(loaderwork.state);
loaderwork.state = 0;
}
loaderwork.statesize = 0;
}
static int load_map(int issave, unsigned char *udata, unsigned usize)
{
unsigned char *iptr;
unsigned isize;
unsigned char *xptr;
unsigned xsize = getdwordle(udata + 4);
unsigned xofs = getdwordle(udata + 0);
if (issave)
{
iptr = loaderwork.state;
isize = loaderwork.statesize;
loaderwork.state = 0;
loaderwork.statesize = 0;
}
else
{
iptr = loaderwork.rom;
isize = loaderwork.romsize;
loaderwork.rom = 0;
loaderwork.romsize = 0;
}
if (!iptr)
{
unsigned rsize = xofs + xsize;
if (!issave)
{
rsize -= 1;
rsize |= rsize >> 1;
rsize |= rsize >> 2;
rsize |= rsize >> 4;
rsize |= rsize >> 8;
rsize |= rsize >> 16;
rsize += 1;
}
iptr = malloc(rsize + 10);
if (!iptr)
return XSF_FALSE;
memset(iptr, 0, rsize + 10);
isize = rsize;
}
else if (isize < xofs + xsize)
{
unsigned rsize = xofs + xsize;
if (!issave)
{
rsize -= 1;
rsize |= rsize >> 1;
rsize |= rsize >> 2;
rsize |= rsize >> 4;
rsize |= rsize >> 8;
rsize |= rsize >> 16;
rsize += 1;
}
xptr = realloc(iptr, xofs + rsize + 10);
if (!xptr)
{
free(iptr);
return XSF_FALSE;
}
iptr = xptr;
isize = rsize;
}
memcpy(iptr + xofs, udata + 8, xsize);
if (issave)
{
loaderwork.state = iptr;
loaderwork.statesize = isize;
}
else
{
loaderwork.rom = iptr;
loaderwork.romsize = isize;
}
return XSF_TRUE;
}
static int load_mapz(int issave, unsigned char *zdata, unsigned zsize, unsigned zcrc)
{
int ret;
int zerr;
uLongf usize = 8;
uLongf rsize = usize;
unsigned char *udata;
unsigned char *rdata;
udata = malloc(usize);
if (!udata)
return XSF_FALSE;
while (Z_OK != (zerr = uncompress(udata, &usize, zdata, zsize)))
{
if (Z_MEM_ERROR != zerr && Z_BUF_ERROR != zerr)
{
free(udata);
return XSF_FALSE;
}
if (usize >= 8)
{
usize = getdwordle(udata + 4) + 8;
if (usize < rsize)
{
rsize += rsize;
usize = rsize;
}
else
rsize = usize;
}
else
{
rsize += rsize;
usize = rsize;
}
free(udata);
udata = malloc(usize);
if (!udata)
return XSF_FALSE;
}
rdata = realloc(udata, usize);
if (!rdata)
{
free(udata);
return XSF_FALSE;
}
if (0)
{
unsigned ccrc = crc32(crc32(0L, Z_NULL, 0), rdata, usize);
if (ccrc != zcrc)
return XSF_FALSE;
}
ret = load_map(issave, rdata, usize);
free(rdata);
return ret;
}
static int load_psf_one(unsigned char *pfile, unsigned bytes)
{
unsigned char *ptr = pfile;
unsigned code_size;
unsigned resv_size;
unsigned code_crc;
if (bytes < 16 || getdwordle(ptr) != 0x24465350)
return XSF_FALSE;
resv_size = getdwordle(ptr + 4);
code_size = getdwordle(ptr + 8);
code_crc = getdwordle(ptr + 12);
if (resv_size)
{
unsigned resv_pos = 0;
ptr = pfile + 16;
if (16+ resv_size > bytes)
return XSF_FALSE;
while (resv_pos + 12 < resv_size)
{
unsigned save_size = getdwordle(ptr + resv_pos + 4);
unsigned save_crc = getdwordle(ptr + resv_pos + 8);
if (getdwordle(ptr + resv_pos + 0) == 0x45564153)
{
if (resv_pos + 12 + save_size > resv_size)
return XSF_FALSE;
if (!load_mapz(1, ptr + resv_pos + 12, save_size, save_crc))
return XSF_FALSE;
}
resv_pos += 12 + save_size;
}
}
if (code_size)
{
ptr = pfile + 16 + resv_size;
if (16 + resv_size + code_size > bytes)
return XSF_FALSE;
if (!load_mapz(0, ptr, code_size, code_crc))
return XSF_FALSE;
}
return XSF_TRUE;
}
typedef struct
{
const char *tag;
int taglen;
int level;
int found;
} loadlibwork_t;
static int load_psf_and_libs(int level, void *pfile, unsigned bytes);
static int load_psfcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd)
{
loadlibwork_t *pwork = (loadlibwork_t *)pWork;
int ret = xsf_tagenum_callback_returnvaluecontinue;
if (pNameEnd - pNameTop == pwork->taglen && !_strnicmp(pNameTop, pwork->tag , pwork->taglen))
{
unsigned l = pValueEnd - pValueTop;
char *lib = malloc(l + 1);
if (!lib)
{
ret = xsf_tagenum_callback_returnvaluebreak;
}
else
{
void *libbuf;
unsigned libsize;
memcpy(lib, pValueTop, l);
lib[l] = '\0';
if (!xsf_get_lib(lib, &libbuf, &libsize))
{
ret = xsf_tagenum_callback_returnvaluebreak;
}
else
{
if (!load_psf_and_libs(pwork->level + 1, libbuf, libsize))
ret = xsf_tagenum_callback_returnvaluebreak;
else
pwork->found++;
free(libbuf);
}
free(lib);
}
}
return ret;
}
static int load_psf_and_libs(int level, void *pfile, unsigned bytes)
{
int haslib = 0;
loadlibwork_t work;
work.level = level;
work.tag = "_lib";
work.taglen = strlen(work.tag);
work.found = 0;
if (level <= 10 && xsf_tagenum(load_psfcb, &work, pfile, bytes) < 0)
return XSF_FALSE;
haslib = work.found;
if (!load_psf_one(pfile, bytes))
return XSF_FALSE;
/* if (haslib) */
{
int n = 2;
do
{
char tbuf[16];
#ifdef HAVE_SPRINTF_S
sprintf_s(tbuf, sizeof(tbuf), "_lib%d", n++);
#else
sprintf(tbuf, "_lib%d", n++);
#endif
work.tag = tbuf;
work.taglen = strlen(work.tag);
work.found = 0;
if (xsf_tagenum(load_psfcb, &work, pfile, bytes) < 0)
return XSF_FALSE;
}
while (work.found);
}
return XSF_TRUE;
}
static int load_psf(void *pfile, unsigned bytes)
{
load_term();
return load_psf_and_libs(1, pfile, bytes);
}
static void load_getstateinit(unsigned ptr)
{
loaderwork.stateptr = ptr;
}
static u16 getwordle(const unsigned char *pData)
{
return pData[0] | (((u16)pData[1]) << 8);
}
static void load_getsta(Status_Reg *ptr, unsigned l)
{
unsigned s = l << 2;
unsigned i;
if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
return;
for (i = 0; i < l; i++)
{
u32 st = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
ptr[i].bits.N = (st >> 31) & 1;
ptr[i].bits.Z = (st >> 30) & 1;
ptr[i].bits.C = (st >> 29) & 1;
ptr[i].bits.V = (st >> 28) & 1;
ptr[i].bits.Q = (st >> 27) & 1;
ptr[i].bits.RAZ = (st >> 8) & ((1 << 19) - 1);
ptr[i].bits.I = (st >> 7) & 1;
ptr[i].bits.F = (st >> 6) & 1;
ptr[i].bits.T = (st >> 5) & 1;
ptr[i].bits.mode = (st >> 0) & 0x1f;
}
loaderwork.stateptr += s;
}
static void load_getbool(BOOL *ptr, unsigned l)
{
unsigned s = l << 2;
unsigned i;
if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
return;
for (i = 0; i < l; i++)
ptr[i] = (BOOL)getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
loaderwork.stateptr += s;
}
#if defined(SIGNED_IS_NOT_2S_COMPLEMENT)
/* 2's complement */
#define u32tos32(v) ((s32)((((s64)(v)) ^ 0x80000000) - 0x80000000))
#else
/* 2's complement */
#define u32tos32(v) ((s32)v)
#endif
static void load_gets32(s32 *ptr, unsigned l)
{
unsigned s = l << 2;
unsigned i;
if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
return;
for (i = 0; i < l; i++)
ptr[i] = u32tos32(getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)));
loaderwork.stateptr += s;
}
static void load_getu32(u32 *ptr, unsigned l)
{
unsigned s = l << 2;
unsigned i;
if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
return;
for (i = 0; i < l; i++)
ptr[i] = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
loaderwork.stateptr += s;
}
static void load_getu16(u16 *ptr, unsigned l)
{
unsigned s = l << 1;
unsigned i;
if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
return;
for (i = 0; i < l; i++)
ptr[i] = getwordle(loaderwork.state + loaderwork.stateptr + (i << 1));
loaderwork.stateptr += s;
}
static void load_getu8(u8 *ptr, unsigned l)
{
unsigned s = l;
unsigned i;
if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
return;
for (i = 0; i < l; i++)
ptr[i] = loaderwork.state[loaderwork.stateptr + i];
loaderwork.stateptr += s;
}
void gdb_stub_fix(armcpu_t *armcpu)
{
/* armcpu->R[15] = armcpu->instruct_adr; */
armcpu->next_instruction = armcpu->instruct_adr;
if(armcpu->CPSR.bits.T == 0)
{
armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
armcpu->instruct_adr = armcpu->next_instruction;
armcpu->next_instruction += 4;
armcpu->R[15] = armcpu->next_instruction + 4;
}
else
{
armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
armcpu->instruct_adr = armcpu->next_instruction;
armcpu->next_instruction += 2;
armcpu->R[15] = armcpu->next_instruction + 2;
}
}
static void load_setstate(void)
{
if (!loaderwork.statesize)
return;
/* Skip over "Desmume Save File" crap */
load_getstateinit(0x17);
/* Read ARM7 cpu registers */
load_getu32(&NDS_ARM7.proc_ID, 1);
load_getu32(&NDS_ARM7.instruction, 1);
load_getu32(&NDS_ARM7.instruct_adr, 1);
load_getu32(&NDS_ARM7.next_instruction, 1);
load_getu32(NDS_ARM7.R, 16);
load_getsta(&NDS_ARM7.CPSR, 1);
load_getsta(&NDS_ARM7.SPSR, 1);
load_getu32(&NDS_ARM7.R13_usr, 1);
load_getu32(&NDS_ARM7.R14_usr, 1);
load_getu32(&NDS_ARM7.R13_svc, 1);
load_getu32(&NDS_ARM7.R14_svc, 1);
load_getu32(&NDS_ARM7.R13_abt, 1);
load_getu32(&NDS_ARM7.R14_abt, 1);
load_getu32(&NDS_ARM7.R13_und, 1);
load_getu32(&NDS_ARM7.R14_und, 1);
load_getu32(&NDS_ARM7.R13_irq, 1);
load_getu32(&NDS_ARM7.R14_irq, 1);
load_getu32(&NDS_ARM7.R8_fiq, 1);
load_getu32(&NDS_ARM7.R9_fiq, 1);
load_getu32(&NDS_ARM7.R10_fiq, 1);
load_getu32(&NDS_ARM7.R11_fiq, 1);
load_getu32(&NDS_ARM7.R12_fiq, 1);
load_getu32(&NDS_ARM7.R13_fiq, 1);
load_getu32(&NDS_ARM7.R14_fiq, 1);
load_getsta(&NDS_ARM7.SPSR_svc, 1);
load_getsta(&NDS_ARM7.SPSR_abt, 1);
load_getsta(&NDS_ARM7.SPSR_und, 1);
load_getsta(&NDS_ARM7.SPSR_irq, 1);
load_getsta(&NDS_ARM7.SPSR_fiq, 1);
load_getu32(&NDS_ARM7.intVector, 1);
load_getu8(&NDS_ARM7.LDTBit, 1);
load_getbool(&NDS_ARM7.waitIRQ, 1);
load_getbool(&NDS_ARM7.wIRQ, 1);
load_getbool(&NDS_ARM7.wirq, 1);
/* Read ARM9 cpu registers */
load_getu32(&NDS_ARM9.proc_ID, 1);
load_getu32(&NDS_ARM9.instruction, 1);
load_getu32(&NDS_ARM9.instruct_adr, 1);
load_getu32(&NDS_ARM9.next_instruction, 1);
load_getu32(NDS_ARM9.R, 16);
load_getsta(&NDS_ARM9.CPSR, 1);
load_getsta(&NDS_ARM9.SPSR, 1);
load_getu32(&NDS_ARM9.R13_usr, 1);
load_getu32(&NDS_ARM9.R14_usr, 1);
load_getu32(&NDS_ARM9.R13_svc, 1);
load_getu32(&NDS_ARM9.R14_svc, 1);
load_getu32(&NDS_ARM9.R13_abt, 1);
load_getu32(&NDS_ARM9.R14_abt, 1);
load_getu32(&NDS_ARM9.R13_und, 1);
load_getu32(&NDS_ARM9.R14_und, 1);
load_getu32(&NDS_ARM9.R13_irq, 1);
load_getu32(&NDS_ARM9.R14_irq, 1);
load_getu32(&NDS_ARM9.R8_fiq, 1);
load_getu32(&NDS_ARM9.R9_fiq, 1);
load_getu32(&NDS_ARM9.R10_fiq, 1);
load_getu32(&NDS_ARM9.R11_fiq, 1);
load_getu32(&NDS_ARM9.R12_fiq, 1);
load_getu32(&NDS_ARM9.R13_fiq, 1);
load_getu32(&NDS_ARM9.R14_fiq, 1);
load_getsta(&NDS_ARM9.SPSR_svc, 1);
load_getsta(&NDS_ARM9.SPSR_abt, 1);
load_getsta(&NDS_ARM9.SPSR_und, 1);
load_getsta(&NDS_ARM9.SPSR_irq, 1);
load_getsta(&NDS_ARM9.SPSR_fiq, 1);
load_getu32(&NDS_ARM9.intVector, 1);
load_getu8(&NDS_ARM9.LDTBit, 1);
load_getbool(&NDS_ARM9.waitIRQ, 1);
load_getbool(&NDS_ARM9.wIRQ, 1);
load_getbool(&NDS_ARM9.wirq, 1);
/* Read in other internal variables that are important */
load_gets32(&nds.ARM9Cycle, 1);
load_gets32(&nds.ARM7Cycle, 1);
load_gets32(&nds.cycles, 1);
load_gets32(nds.timerCycle[0], 4);
load_gets32(nds.timerCycle[1], 4);
load_getbool(nds.timerOver[0], 4);
load_getbool(nds.timerOver[1], 4);
load_gets32(&nds.nextHBlank, 1);
load_getu32(&nds.VCount, 1);
load_getu32(&nds.old, 1);
load_gets32(&nds.diff, 1);
load_getbool(&nds.lignerendu, 1);
load_getu16(&nds.touchX, 1);
load_getu16(&nds.touchY, 1);
/* Read in memory/registers specific to the ARM9 */
load_getu8 (ARM9Mem.ARM9_ITCM, 0x8000);
load_getu8 (ARM9Mem.ARM9_DTCM, 0x4000);
load_getu8 (ARM9Mem.ARM9_WRAM, 0x1000000);
load_getu8 (ARM9Mem.MAIN_MEM, 0x400000);
load_getu8 (ARM9Mem.ARM9_REG, 0x10000);
load_getu8 (ARM9Mem.ARM9_VMEM, 0x800);
load_getu8 (ARM9Mem.ARM9_OAM, 0x800);
load_getu8 (ARM9Mem.ARM9_ABG, 0x80000);
load_getu8 (ARM9Mem.ARM9_BBG, 0x20000);
load_getu8 (ARM9Mem.ARM9_AOBJ, 0x40000);
load_getu8 (ARM9Mem.ARM9_BOBJ, 0x20000);
load_getu8 (ARM9Mem.ARM9_LCD, 0xA4000);
/* Read in memory/registers specific to the ARM7 */
load_getu8 (MMU.ARM7_ERAM, 0x10000);
load_getu8 (MMU.ARM7_REG, 0x10000);
load_getu8 (MMU.ARM7_WIRAM, 0x10000);
/* Read in shared memory */
load_getu8 (MMU.SWIRAM, 0x8000);
#ifdef GDB_STUB
#else
gdb_stub_fix(&NDS_ARM9);
gdb_stub_fix(&NDS_ARM7);
#endif
}
static struct
{
unsigned char *pcmbufalloc;
unsigned char *pcmbuftop;
unsigned filled;
unsigned used;
u32 bufferbytes;
u32 cycles;
int xfs_load;
int sync_type;
int arm7_clockdown_level;
int arm9_clockdown_level;
} sndifwork = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static void SNDIFDeInit(void)
{
if (sndifwork.pcmbufalloc)
{
free(sndifwork.pcmbufalloc);
sndifwork.pcmbufalloc = 0;
sndifwork.pcmbuftop = 0;
sndifwork.bufferbytes = 0;
}
}
static int SNDIFInit(int buffersize)
{
u32 bufferbytes = buffersize * sizeof(s16);
SNDIFDeInit();
sndifwork.pcmbufalloc = malloc(bufferbytes + 3);
if (!sndifwork.pcmbufalloc)
return -1;
sndifwork.pcmbuftop = sndifwork.pcmbufalloc + ((4 - (((int)sndifwork.pcmbufalloc) & 3)) & 3);
sndifwork.bufferbytes = bufferbytes;
sndifwork.filled = 0;
sndifwork.used = 0;
sndifwork.cycles = 0;
return 0;
}
static void SNDIFMuteAudio(void)
{
}
static void SNDIFUnMuteAudio(void)
{
}
static void SNDIFSetVolume(int volume)
{
}
static int SNDIFGetAudioSpace(void)
{
return sndifwork.bufferbytes >> 2; // bytes to samples
}
static void SNDIFUpdateAudio(s16 * buffer, u32 num_samples)
{
u32 num_bytes = num_samples << 2;
if (num_bytes > sndifwork.bufferbytes) num_bytes = sndifwork.bufferbytes;
memcpy(sndifwork.pcmbuftop, buffer, num_bytes);
sndifwork.filled = num_bytes;
sndifwork.used = 0;
}
#define VIO2SFSNDIFID 0
static SoundInterface_struct VIO2SFSNDIF =
{
VIO2SFSNDIFID,
"vio2sf Sound Interface",
SNDIFInit,
SNDIFDeInit,
SNDIFUpdateAudio,
SNDIFGetAudioSpace,
SNDIFMuteAudio,
SNDIFUnMuteAudio,
SNDIFSetVolume
};
SoundInterface_struct *SNDCoreList[] = {
&VIO2SFSNDIF,
NULL
};
static struct armcpu_ctrl_iface *arm9_ctrl_iface = 0;
static struct armcpu_ctrl_iface *arm7_ctrl_iface = 0;
int xsf_start(void *pfile, unsigned bytes)
{
int frames = xsf_tagget_int("_frames", pfile, bytes, -1);
int clockdown = xsf_tagget_int("_clockdown", pfile, bytes, 0);
sndifwork.sync_type = xsf_tagget_int("_vio2sf_sync_type", pfile, bytes, 0);
sndifwork.arm9_clockdown_level = xsf_tagget_int("_vio2sf_arm9_clockdown_level", pfile, bytes, clockdown);
sndifwork.arm7_clockdown_level = xsf_tagget_int("_vio2sf_arm7_clockdown_level", pfile, bytes, clockdown);
sndifwork.xfs_load = 0;
if (!load_psf(pfile, bytes))
return XSF_FALSE;
#ifdef GDB_STUB
if (NDS_Init(&arm9_base_memory_iface, &arm9_ctrl_iface, &arm7_base_memory_iface, &arm7_ctrl_iface))
#else
if (NDS_Init())
#endif
return XSF_FALSE;
SPU_ChangeSoundCore(0, 737);
execute = FALSE;
MMU_unsetRom();
if (loaderwork.rom)
{
NDS_SetROM(loaderwork.rom, loaderwork.romsize - 1);
}
NDS_Reset();
execute = TRUE;
if (loaderwork.state)
{
armcp15_t *c9 = (armcp15_t *)NDS_ARM9.coproc[15];
int proc;
if (frames == -1)
{
/* set initial ARM9 coprocessor state */
armcp15_moveARM2CP(c9, 0x00000000, 0x01, 0x00, 0, 0);
armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x05, 0, 0);
armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x06, 0, 0);
armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
armcp15_moveARM2CP(c9, 0x04000033, 0x06, 0x00, 0, 4);
armcp15_moveARM2CP(c9, 0x0200002d, 0x06, 0x01, 0, 0);
armcp15_moveARM2CP(c9, 0x027e0021, 0x06, 0x02, 0, 0);
armcp15_moveARM2CP(c9, 0x08000035, 0x06, 0x03, 0, 0);
armcp15_moveARM2CP(c9, 0x027e001b, 0x06, 0x04, 0, 0);
armcp15_moveARM2CP(c9, 0x0100002f, 0x06, 0x05, 0, 0);
armcp15_moveARM2CP(c9, 0xffff001d, 0x06, 0x06, 0, 0);
armcp15_moveARM2CP(c9, 0x027ff017, 0x06, 0x07, 0, 0);
armcp15_moveARM2CP(c9, 0x00000020, 0x09, 0x01, 0, 1);
armcp15_moveARM2CP(c9, 0x027e000a, 0x09, 0x01, 0, 0);
armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 1);
armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 0);
armcp15_moveARM2CP(c9, 0x00000002, 0x03, 0x00, 0, 0);
armcp15_moveARM2CP(c9, 0x05100011, 0x05, 0x00, 0, 3);
armcp15_moveARM2CP(c9, 0x15111011, 0x05, 0x00, 0, 2);
armcp15_moveARM2CP(c9, 0x07dd1e10, 0x01, 0x00, 0, 0);
armcp15_moveARM2CP(c9, 0x0005707d, 0x01, 0x00, 0, 0);
armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x05, 0, 1);
armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x0e, 0, 1);
/* set initial timer state */
MMU_write16(0, REG_TM0CNTL, 0x0000);
MMU_write16(0, REG_TM0CNTH, 0x00C1);
MMU_write16(1, REG_TM0CNTL, 0x0000);
MMU_write16(1, REG_TM0CNTH, 0x00C1);
MMU_write16(1, REG_TM1CNTL, 0xf7e7);
MMU_write16(1, REG_TM1CNTH, 0x00C1);
/* set initial interrupt state */
MMU.reg_IME[0] = 0x00000001;
MMU.reg_IE[0] = 0x00042001;
MMU.reg_IME[1] = 0x00000001;
MMU.reg_IE[1] = 0x0104009d;
}
else if (frames > 0)
{
/* execute boot code */
int i;
for (i=0; i<frames; i++)
NDS_exec_frame(0, 0);
i = 0;
}
/* load state */
load_setstate();
free(loaderwork.state);
loaderwork.state = 0;
if (frames == -1)
{
armcp15_moveARM2CP(c9, (NDS_ARM9.R13_irq & 0x0fff0000) | 0x0a, 0x09, 0x01, 0, 0);
}
/* restore timer state */
for (proc = 0; proc < 2; proc++)
{
MMU_write16(proc, REG_TM0CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM0CNTH & 0xFFF));
MMU_write16(proc, REG_TM1CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM1CNTH & 0xFFF));
MMU_write16(proc, REG_TM2CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM2CNTH & 0xFFF));
MMU_write16(proc, REG_TM3CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM3CNTH & 0xFFF));
}
}
else if (frames > 0)
{
/* skip 1 sec */
int i;
for (i=0; i<frames; i++)
NDS_exec_frame(0, 0);
}
execute = TRUE;
sndifwork.xfs_load = 1;
return XSF_TRUE;
}
int xsf_gen(void *pbuffer, unsigned samples)
{
unsigned char *ptr = pbuffer;
unsigned bytes = samples <<= 2;
if (!sndifwork.xfs_load) return 0;
while (bytes)
{
unsigned remainbytes = sndifwork.filled - sndifwork.used;
if (remainbytes > 0)
{
if (remainbytes > bytes)
{
memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, bytes);
sndifwork.used += bytes;
ptr += bytes;
remainbytes -= bytes; /**/
bytes = 0; /**/
break;
}
else
{
memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, remainbytes);
sndifwork.used += remainbytes;
ptr += remainbytes;
bytes -= remainbytes;
remainbytes = 0;
}
}
if (remainbytes == 0)
{
/*
#define HBASE_CYCLES (16756000*2)
#define HBASE_CYCLES (33512000*1)
#define HBASE_CYCLES (33509300.322234)
*/
#define HBASE_CYCLES (33509300.322234)
#define HLINE_CYCLES (6 * (99 + 256))
#define HSAMPLES ((u32)((44100.0 * HLINE_CYCLES) / HBASE_CYCLES))
#define VDIVISION 100
#define VLINES 263
#define VBASE_CYCLES (((double)HBASE_CYCLES) / VDIVISION)
#define VSAMPLES ((u32)((44100.0 * HLINE_CYCLES * VLINES) / HBASE_CYCLES))
int numsamples;
if (sndifwork.sync_type == 1)
{
/* vsync */
sndifwork.cycles += ((44100 / VDIVISION) * HLINE_CYCLES * VLINES);
if (sndifwork.cycles >= (u32)(VBASE_CYCLES * (VSAMPLES + 1)))
{
numsamples = (VSAMPLES + 1);
sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 1));
}
else
{
numsamples = (VSAMPLES + 0);
sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 0));
}
NDS_exec_frame(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level);
}
else
{
/* hsync */
sndifwork.cycles += (44100 * HLINE_CYCLES);
if (sndifwork.cycles >= (u32)(HBASE_CYCLES * (HSAMPLES + 1)))
{
numsamples = (HSAMPLES + 1);
sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 1));
}
else
{
numsamples = (HSAMPLES + 0);
sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 0));
}
NDS_exec_hframe(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level);
}
SPU_EmulateSamples(numsamples);
}
}
return ptr - (unsigned char *)pbuffer;
}
void xsf_term(void)
{
MMU_unsetRom();
NDS_DeInit();
load_term();
}

View File

@ -0,0 +1,149 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
#define BASE 65521UL /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware */
#ifdef NO_DIVIDE
# define MOD(a) \
do { \
if (a >= (BASE << 16)) a -= (BASE << 16); \
if (a >= (BASE << 15)) a -= (BASE << 15); \
if (a >= (BASE << 14)) a -= (BASE << 14); \
if (a >= (BASE << 13)) a -= (BASE << 13); \
if (a >= (BASE << 12)) a -= (BASE << 12); \
if (a >= (BASE << 11)) a -= (BASE << 11); \
if (a >= (BASE << 10)) a -= (BASE << 10); \
if (a >= (BASE << 9)) a -= (BASE << 9); \
if (a >= (BASE << 8)) a -= (BASE << 8); \
if (a >= (BASE << 7)) a -= (BASE << 7); \
if (a >= (BASE << 6)) a -= (BASE << 6); \
if (a >= (BASE << 5)) a -= (BASE << 5); \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
# define MOD4(a) \
do { \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
#else
# define MOD(a) a %= BASE
# define MOD4(a) a %= BASE
#endif
/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
uLong adler;
const Bytef *buf;
uInt len;
{
unsigned long sum2;
unsigned n;
/* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD4(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while (len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}
/* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off_t len2;
{
unsigned long sum1;
unsigned long sum2;
unsigned rem;
/* the derivation of this formula is left as an exercise for the reader */
rem = (unsigned)(len2 % BASE);
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 > BASE) sum1 -= BASE;
if (sum1 > BASE) sum1 -= BASE;
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 > BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
}

View File

@ -0,0 +1,17 @@
All files under this contrib directory are UNSUPPORTED. There were
provided by users of zlib and were not tested by the authors of zlib.
Use at your own risk. Please contact the authors of the contributions
for help about these, not the zlib authors. Thanks.
inflate86/ by Chris Anderson <christop@charm.net>
Tuned x86 gcc asm code to replace inflate_fast()
masmx64/ by Gilles Vollant <info@winimage.com>
x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
replace longest_match() and inflate_fast()
masmx86/ by Gilles Vollant <info@winimage.com>
x86 asm code to replace longest_match() and inflate_fast(),
for Visual C++ and MASM

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
ml64.exe /Flgvmat64 /c /Zi gvmat64.asm

View File

@ -0,0 +1,513 @@
;uInt longest_match_x64(
; deflate_state *s,
; IPos cur_match); /* current match */
; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86
; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
;
; File written by Gilles Vollant, by converting to assembly the longest_match
; from Jean-loup Gailly in deflate.c of zLib and infoZip zip.
;
; and by taking inspiration on asm686 with masm, optimised assembly code
; from Brian Raiter, written 1998
;
; http://www.zlib.net
; http://www.winimage.com/zLibDll
; http://www.muppetlabs.com/~breadbox/software/assembly.html
;
; to compile this file for infozip Zip, I use option:
; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm
;
; to compile this file for zLib, I use option:
; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm
; Be carrefull to adapt zlib1222add below to your version of zLib
; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change
; value of zlib1222add later)
;
; This file compile with Microsoft Macro Assembler (x64) for AMD64
;
; ml64.exe is given with Visual Studio 2005 and Windows 2003 server DDK
;
; (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from
; http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
;
;uInt longest_match(s, cur_match)
; deflate_state *s;
; IPos cur_match; /* current match */
.code
longest_match PROC
;LocalVarsSize equ 88
LocalVarsSize equ 72
; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12
; free register : r14,r15
; register can be saved : rsp
chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len
; low word: s->wmask
;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10
;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11
;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w
;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx
;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13
;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d
;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9
IFDEF INFOZIP
ELSE
nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size
ENDIF
save_rdi equ rsp + 24 - LocalVarsSize
save_rsi equ rsp + 32 - LocalVarsSize
save_rbx equ rsp + 40 - LocalVarsSize
save_rbp equ rsp + 48 - LocalVarsSize
save_r12 equ rsp + 56 - LocalVarsSize
save_r13 equ rsp + 64 - LocalVarsSize
;save_r14 equ rsp + 72 - LocalVarsSize
;save_r15 equ rsp + 80 - LocalVarsSize
; all the +4 offsets are due to the addition of pending_buf_size (in zlib
; in the deflate_state structure since the asm code was first written
; (if you compile with zlib 1.0.4 or older, remove the +4).
; Note : these value are good with a 8 bytes boundary pack structure
MAX_MATCH equ 258
MIN_MATCH equ 3
MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
;;; Offsets for fields in the deflate_state structure. These numbers
;;; are calculated from the definition of deflate_state, with the
;;; assumption that the compiler will dword-align the fields. (Thus,
;;; changing the definition of deflate_state could easily cause this
;;; program to crash horribly, without so much as a warning at
;;; compile time. Sigh.)
; all the +zlib1222add offsets are due to the addition of fields
; in zlib in the deflate_state structure since the asm code was first written
; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
IFDEF INFOZIP
_DATA SEGMENT
COMM window_size:DWORD
; WMask ; 7fff
COMM window:BYTE:010040H
COMM prev:WORD:08000H
; MatchLen : unused
; PrevMatch : unused
COMM strstart:DWORD
COMM match_start:DWORD
; Lookahead : ignore
COMM prev_length:DWORD ; PrevLen
COMM max_chain_length:DWORD
COMM good_match:DWORD
COMM nice_match:DWORD
prev_ad equ OFFSET prev
window_ad equ OFFSET window
nicematch equ nice_match
_DATA ENDS
WMask equ 07fffh
ELSE
IFNDEF zlib1222add
zlib1222add equ 8
ENDIF
dsWSize equ 56+zlib1222add+(zlib1222add/2)
dsWMask equ 64+zlib1222add+(zlib1222add/2)
dsWindow equ 72+zlib1222add
dsPrev equ 88+zlib1222add
dsMatchLen equ 128+zlib1222add
dsPrevMatch equ 132+zlib1222add
dsStrStart equ 140+zlib1222add
dsMatchStart equ 144+zlib1222add
dsLookahead equ 148+zlib1222add
dsPrevLen equ 152+zlib1222add
dsMaxChainLen equ 156+zlib1222add
dsGoodMatch equ 172+zlib1222add
dsNiceMatch equ 176+zlib1222add
window_size equ [ rcx + dsWSize]
WMask equ [ rcx + dsWMask]
window_ad equ [ rcx + dsWindow]
prev_ad equ [ rcx + dsPrev]
strstart equ [ rcx + dsStrStart]
match_start equ [ rcx + dsMatchStart]
Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip
prev_length equ [ rcx + dsPrevLen]
max_chain_length equ [ rcx + dsMaxChainLen]
good_match equ [ rcx + dsGoodMatch]
nice_match equ [ rcx + dsNiceMatch]
ENDIF
; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)
; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
;
; All registers must be preserved across the call, except for
; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch.
;;; Save registers that the compiler may be using, and adjust esp to
;;; make room for our stack frame.
;;; Retrieve the function arguments. r8d will hold cur_match
;;; throughout the entire function. edx will hold the pointer to the
;;; deflate_state structure during the function's setup (before
;;; entering the main loop.
; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)
; this clear high 32 bits of r8, which can be garbage in both r8 and rdx
mov [save_rdi],rdi
mov [save_rsi],rsi
mov [save_rbx],rbx
mov [save_rbp],rbp
IFDEF INFOZIP
mov r8d,ecx
ELSE
mov r8d,edx
ENDIF
mov [save_r12],r12
mov [save_r13],r13
; mov [save_r14],r14
; mov [save_r15],r15
;;; uInt wmask = s->w_mask;
;;; unsigned chain_length = s->max_chain_length;
;;; if (s->prev_length >= s->good_match) {
;;; chain_length >>= 2;
;;; }
mov edi, prev_length
mov esi, good_match
mov eax, WMask
mov ebx, max_chain_length
cmp edi, esi
jl LastMatchGood
shr ebx, 2
LastMatchGood:
;;; chainlen is decremented once beforehand so that the function can
;;; use the sign flag instead of the zero flag for the exit test.
;;; It is then shifted into the high word, to make room for the wmask
;;; value, which it will always accompany.
dec ebx
shl ebx, 16
or ebx, eax
;;; on zlib only
;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
IFDEF INFOZIP
mov [chainlenwmask], ebx
; on infozip nice_match = [nice_match]
ELSE
mov eax, nice_match
mov [chainlenwmask], ebx
mov r10d, Lookahead
cmp r10d, eax
cmovnl r10d, eax
mov [nicematch],r10d
ENDIF
;;; register Bytef *scan = s->window + s->strstart;
mov r10, window_ad
mov ebp, strstart
lea r13, [r10 + rbp]
;;; Determine how many bytes the scan ptr is off from being
;;; dword-aligned.
mov r9,r13
neg r13
and r13,3
;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
;;; s->strstart - (IPos)MAX_DIST(s) : NIL;
IFDEF INFOZIP
mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1))
ELSE
mov eax, window_size
sub eax, MIN_LOOKAHEAD
ENDIF
xor edi,edi
sub ebp, eax
mov r11d, prev_length
cmovng ebp,edi
;;; int best_len = s->prev_length;
;;; Store the sum of s->window + best_len in esi locally, and in esi.
lea rsi,[r10+r11]
;;; register ush scan_start = *(ushf*)scan;
;;; register ush scan_end = *(ushf*)(scan+best_len-1);
;;; Posf *prev = s->prev;
movzx r12d,word ptr [r9]
movzx ebx, word ptr [r9 + r11 - 1]
mov rdi, prev_ad
;;; Jump into the main loop.
mov edx, [chainlenwmask]
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop1:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry1:
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop2:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry2:
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop4:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry4:
cmp bx,word ptr [rsi + r8 - 1]
jnz LookupLoop1
jmp LookupLoopIsZero
;;; do {
;;; match = s->window + cur_match;
;;; if (*(ushf*)(match+best_len-1) != scan_end ||
;;; *(ushf*)match != scan_start) continue;
;;; [...]
;;; } while ((cur_match = prev[cur_match & wmask]) > limit
;;; && --chain_length != 0);
;;;
;;; Here is the inner loop of the function. The function will spend the
;;; majority of its time in this loop, and majority of that time will
;;; be spent in the first ten instructions.
;;;
;;; Within this loop:
;;; ebx = scanend
;;; r8d = curmatch
;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
;;; esi = windowbestlen - i.e., (window + bestlen)
;;; edi = prev
;;; ebp = limit
LookupLoop:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry:
cmp bx,word ptr [rsi + r8 - 1]
jnz LookupLoop1
LookupLoopIsZero:
cmp r12w, word ptr [r10 + r8]
jnz LookupLoop1
;;; Store the current value of chainlen.
mov [chainlenwmask], edx
;;; Point edi to the string under scrutiny, and esi to the string we
;;; are hoping to match it up with. In actuality, esi and edi are
;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
;;; initialized to -(MAX_MATCH_8 - scanalign).
lea rsi,[r8+r10]
mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)
lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]
lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]
prefetcht1 [rsi+rdx]
prefetcht1 [rdi+rdx]
;;; Test the strings for equality, 8 bytes at a time. At the end,
;;; adjust rdx so that it is offset to the exact byte that mismatched.
;;;
;;; We already know at this point that the first three bytes of the
;;; strings match each other, and they can be safely passed over before
;;; starting the compare loop. So what this code does is skip over 0-3
;;; bytes, as much as necessary in order to dword-align the edi
;;; pointer. (rsi will still be misaligned three times out of four.)
;;;
;;; It should be confessed that this loop usually does not represent
;;; much of the total running time. Replacing it with a more
;;; straightforward "rep cmpsb" would not drastically degrade
;;; performance.
LoopCmps:
mov rax, [rsi + rdx]
xor rax, [rdi + rdx]
jnz LeaveLoopCmps
mov rax, [rsi + rdx + 8]
xor rax, [rdi + rdx + 8]
jnz LeaveLoopCmps8
mov rax, [rsi + rdx + 8+8]
xor rax, [rdi + rdx + 8+8]
jnz LeaveLoopCmps16
add rdx,8+8+8
jmp short LoopCmps
LeaveLoopCmps16: add rdx,8
LeaveLoopCmps8: add rdx,8
LeaveLoopCmps:
test eax, 0000FFFFh
jnz LenLower
test eax,0ffffffffh
jnz LenLower32
add rdx,4
shr rax,32
or ax,ax
jnz LenLower
LenLower32:
shr eax,16
add rdx,2
LenLower: sub al, 1
adc rdx, 0
;;; Calculate the length of the match. If it is longer than MAX_MATCH,
;;; then automatically accept it as the best possible match and leave.
lea rax, [rdi + rdx]
sub rax, r9
cmp eax, MAX_MATCH
jge LenMaximum
;;; If the length of the match is not longer than the best match we
;;; have so far, then forget it and return to the lookup loop.
;///////////////////////////////////
cmp eax, r11d
jg LongerMatch
lea rsi,[r10+r11]
mov rdi, prev_ad
mov edx, [chainlenwmask]
jmp LookupLoop
;;; s->match_start = cur_match;
;;; best_len = len;
;;; if (len >= nice_match) break;
;;; scan_end = *(ushf*)(scan+best_len-1);
LongerMatch:
mov r11d, eax
mov match_start, r8d
cmp eax, [nicematch]
jge LeaveNow
lea rsi,[r10+rax]
movzx ebx, word ptr [r9 + rax - 1]
mov rdi, prev_ad
mov edx, [chainlenwmask]
jmp LookupLoop
;;; Accept the current string, with the maximum possible length.
LenMaximum:
mov r11d,MAX_MATCH
mov match_start, r8d
;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
;;; return s->lookahead;
LeaveNow:
IFDEF INFOZIP
mov eax,r11d
ELSE
mov eax, Lookahead
cmp r11d, eax
cmovng eax, r11d
ENDIF
;;; Restore the stack and return from whence we came.
mov rsi,[save_rsi]
mov rdi,[save_rdi]
mov rbx,[save_rbx]
mov rbp,[save_rbp]
mov r12,[save_r12]
mov r13,[save_r13]
; mov r14,[save_r14]
; mov r15,[save_r15]
ret 0
; please don't remove this string !
; Your can freely use gvmat64 in any free or commercial app
; but it is far better don't remove the string in the binary!
db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0
longest_match ENDP
match_init PROC
ret 0
match_init ENDP
END

View File

@ -0,0 +1,186 @@
/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding
* version for AMD64 on Windows using Microsoft C compiler
*
* Copyright (C) 1995-2003 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Copyright (C) 2003 Chris Anderson <christop@charm.net>
* Please use the copyright conditions above.
*
* 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant
*
* inffas8664.c call function inffas8664fnc in inffasx64.asm
* inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
*
* Dec-29-2003 -- I added AMD64 inflate asm support. This version is also
* slightly quicker on x86 systems because, instead of using rep movsb to copy
* data, it uses rep movsw, which moves data in 2-byte chunks instead of single
* bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates
* from http://fedora.linux.duke.edu/fc1_x86_64
* which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with
* 1GB ram. The 64-bit version is about 4% faster than the 32-bit version,
* when decompressing mozilla-source-1.3.tar.gz.
*
* Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
* the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at
* the moment. I have successfully compiled and tested this code with gcc2.96,
* gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S
* compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
* enabled. I will attempt to merge the MMX code into this version. Newer
* versions of this and inffast.S can be found at
* http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
*
*/
#include <stdio.h>
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
/* Mark Adler's comments from inffast.c: */
/*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
available, an end-of-block is encountered, or a data error is encountered.
When large enough input and output buffers are supplied to inflate(), for
example, a 16K input buffer and a 64K output buffer, more than 95% of the
inflate execution time is spent in this routine.
Entry assumptions:
state->mode == LEN
strm->avail_in >= 6
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8
On return, state->mode is one of:
LEN -- ran out of enough output space or enough available input
TYPE -- reached end of block code, inflate() to interpret next block
BAD -- error in block data
Notes:
- The maximum input bits used by a length/distance pair is 15 bits for the
length code, 5 bits for the length extra, 15 bits for the distance code,
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
Therefore if strm->avail_in >= 6, then there is enough input to avoid
checking for available input while decoding.
- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded. inflate_fast()
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
typedef struct inffast_ar {
/* 64 32 x86 x86_64 */
/* ar offset register */
/* 0 0 */ void *esp; /* esp save */
/* 8 4 */ void *ebp; /* ebp save */
/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */
/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */
/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */
/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */
/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */
/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */
/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */
/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */
/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */
/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */
/* 92 48 */ unsigned wsize; /* window size */
/* 96 52 */ unsigned write; /* window write index */
/*100 56 */ unsigned lmask; /* r12 mask for lcode */
/*104 60 */ unsigned dmask; /* r13 mask for dcode */
/*108 64 */ unsigned len; /* r14 match length */
/*112 68 */ unsigned dist; /* r15 match distance */
/*116 72 */ unsigned status; /* set when state chng*/
} type_ar;
#ifdef ASMINF
void inflate_fast(strm, start)
z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{
struct inflate_state FAR *state;
type_ar ar;
void inffas8664fnc(struct inffast_ar * par);
#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64))
#define PAD_AVAIL_IN 6
#define PAD_AVAIL_OUT 258
#else
#define PAD_AVAIL_IN 5
#define PAD_AVAIL_OUT 257
#endif
/* copy state to local variables */
state = (struct inflate_state FAR *)strm->state;
ar.in = strm->next_in;
ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
ar.out = strm->next_out;
ar.beg = ar.out - (start - strm->avail_out);
ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
ar.wsize = state->wsize;
ar.write = state->write;
ar.window = state->window;
ar.hold = state->hold;
ar.bits = state->bits;
ar.lcode = state->lencode;
ar.dcode = state->distcode;
ar.lmask = (1U << state->lenbits) - 1;
ar.dmask = (1U << state->distbits) - 1;
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
/* align in on 1/2 hold size boundary */
while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
ar.hold += (unsigned long)*ar.in++ << ar.bits;
ar.bits += 8;
}
inffas8664fnc(&ar);
if (ar.status > 1) {
if (ar.status == 2)
strm->msg = "invalid literal/length code";
else if (ar.status == 3)
strm->msg = "invalid distance code";
else
strm->msg = "invalid distance too far back";
state->mode = BAD;
}
else if ( ar.status == 1 ) {
state->mode = TYPE;
}
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
ar.len = ar.bits >> 3;
ar.in -= ar.len;
ar.bits -= ar.len << 3;
ar.hold &= (1U << ar.bits) - 1;
/* update state and return */
strm->next_in = ar.in;
strm->next_out = ar.out;
strm->avail_in = (unsigned)(ar.in < ar.last ?
PAD_AVAIL_IN + (ar.last - ar.in) :
PAD_AVAIL_IN - (ar.in - ar.last));
strm->avail_out = (unsigned)(ar.out < ar.end ?
PAD_AVAIL_OUT + (ar.end - ar.out) :
PAD_AVAIL_OUT - (ar.out - ar.end));
state->hold = (unsigned long)ar.hold;
state->bits = ar.bits;
return;
}
#endif

View File

@ -0,0 +1,392 @@
; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding
; version for AMD64 on Windows using Microsoft C compiler
;
; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
; inffasx64.asm is called by inffas8664.c, which contain more info.
; to compile this file, I use option
; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
; with Microsoft Macro Assembler (x64) for AMD64
;
; ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
;
; (you can get Windows 2003 server DDK with ml64 and cl.exe for AMD64 from
; http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
;
.code
inffas8664fnc PROC
; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
;
; All registers must be preserved across the call, except for
; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.
mov [rsp-8],rsi
mov [rsp-16],rdi
mov [rsp-24],r12
mov [rsp-32],r13
mov [rsp-40],r14
mov [rsp-48],r15
mov [rsp-56],rbx
mov rax,rcx
mov [rax+8], rbp ; /* save regs rbp and rsp */
mov [rax], rsp
mov rsp, rax ; /* make rsp point to &ar */
mov rsi, [rsp+16] ; /* rsi = in */
mov rdi, [rsp+32] ; /* rdi = out */
mov r9, [rsp+24] ; /* r9 = last */
mov r10, [rsp+48] ; /* r10 = end */
mov rbp, [rsp+64] ; /* rbp = lcode */
mov r11, [rsp+72] ; /* r11 = dcode */
mov rdx, [rsp+80] ; /* rdx = hold */
mov ebx, [rsp+88] ; /* ebx = bits */
mov r12d, [rsp+100] ; /* r12d = lmask */
mov r13d, [rsp+104] ; /* r13d = dmask */
; /* r14d = len */
; /* r15d = dist */
cld
cmp r10, rdi
je L_one_time ; /* if only one decode left */
cmp r9, rsi
jne L_do_loop
L_one_time:
mov r8, r12 ; /* r8 = lmask */
cmp bl, 32
ja L_get_length_code_one_time
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
jmp L_get_length_code_one_time
ALIGN 4
L_while_test:
cmp r10, rdi
jbe L_break_loop
cmp r9, rsi
jbe L_break_loop
L_do_loop:
mov r8, r12 ; /* r8 = lmask */
cmp bl, 32
ja L_get_length_code ; /* if (32 < bits) */
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
L_get_length_code:
and r8, rdx ; /* r8 &= hold */
mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */
mov cl, ah ; /* cl = this.bits */
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
test al, al
jnz L_test_for_length_base ; /* if (op != 0) 45.7% */
mov r8, r12 ; /* r8 = lmask */
shr eax, 16 ; /* output this.val char */
stosb
L_get_length_code_one_time:
and r8, rdx ; /* r8 &= hold */
mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */
L_dolen:
mov cl, ah ; /* cl = this.bits */
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
test al, al
jnz L_test_for_length_base ; /* if (op != 0) 45.7% */
shr eax, 16 ; /* output this.val char */
stosb
jmp L_while_test
ALIGN 4
L_test_for_length_base:
mov r14d, eax ; /* len = this */
shr r14d, 16 ; /* len = this.val */
mov cl, al
test al, 16
jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */
and cl, 15 ; /* op &= 15 */
jz L_decode_distance ; /* if (!op) */
L_add_bits_to_len:
sub bl, cl
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
shr rdx, cl
add r14d, eax ; /* len += hold & mask[op] */
L_decode_distance:
mov r8, r13 ; /* r8 = dmask */
cmp bl, 32
ja L_get_distance_code ; /* if (32 < bits) */
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
L_get_distance_code:
and r8, rdx ; /* r8 &= hold */
mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */
L_dodist:
mov r15d, eax ; /* dist = this */
shr r15d, 16 ; /* dist = this.val */
mov cl, ah
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
mov cl, al ; /* cl = this.op */
test al, 16 ; /* if ((op & 16) == 0) */
jz L_test_for_second_level_dist
and cl, 15 ; /* op &= 15 */
jz L_check_dist_one
L_add_bits_to_dist:
sub bl, cl
xor eax, eax
inc eax
shl eax, cl
dec eax ; /* (1 << op) - 1 */
and eax, edx ; /* eax &= hold */
shr rdx, cl
add r15d, eax ; /* dist += hold & ((1 << op) - 1) */
L_check_window:
mov r8, rsi ; /* save in so from can use it's reg */
mov rax, rdi
sub rax, [rsp+40] ; /* nbytes = out - beg */
cmp eax, r15d
jb L_clip_window ; /* if (dist > nbytes) 4.2% */
mov ecx, r14d ; /* ecx = len */
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
sar ecx, 1
jnc L_copy_two ; /* if len % 2 == 0 */
rep movsw
mov al, [rsi]
mov [rdi], al
inc rdi
mov rsi, r8 ; /* move in back to %rsi, toss from */
jmp L_while_test
L_copy_two:
rep movsw
mov rsi, r8 ; /* move in back to %rsi, toss from */
jmp L_while_test
ALIGN 4
L_check_dist_one:
cmp r15d, 1 ; /* if dist 1, is a memset */
jne L_check_window
cmp [rsp+40], rdi ; /* if out == beg, outside window */
je L_check_window
mov ecx, r14d ; /* ecx = len */
mov al, [rdi-1]
mov ah, al
sar ecx, 1
jnc L_set_two
mov [rdi], al
inc rdi
L_set_two:
rep stosw
jmp L_while_test
ALIGN 4
L_test_for_second_level_length:
test al, 64
jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
add eax, r14d ; /* eax += len */
mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/
jmp L_dolen
ALIGN 4
L_test_for_second_level_dist:
test al, 64
jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
add eax, r15d ; /* eax += dist */
mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/
jmp L_dodist
ALIGN 4
L_clip_window:
mov ecx, eax ; /* ecx = nbytes */
mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */
neg ecx ; /* nbytes = -nbytes */
cmp eax, r15d
jb L_invalid_distance_too_far ; /* if (dist > wsize) */
add ecx, r15d ; /* nbytes = dist - nbytes */
cmp dword ptr [rsp+96], 0
jne L_wrap_around_window ; /* if (write != 0) */
mov rsi, [rsp+56] ; /* from = window */
sub eax, ecx ; /* eax -= nbytes */
add rsi, rax ; /* from += wsize - nbytes */
mov eax, r14d ; /* eax = len */
cmp r14d, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* eax -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = &out[ -dist ] */
jmp L_do_copy
ALIGN 4
L_wrap_around_window:
mov eax, [rsp+96] ; /* eax = write */
cmp ecx, eax
jbe L_contiguous_in_window ; /* if (write >= nbytes) */
mov esi, [rsp+92] ; /* from = wsize */
add rsi, [rsp+56] ; /* from += window */
add rsi, rax ; /* from += write */
sub rsi, rcx ; /* from -= nbytes */
sub ecx, eax ; /* nbytes -= write */
mov eax, r14d ; /* eax = len */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, [rsp+56] ; /* from = window */
mov ecx, [rsp+96] ; /* nbytes = write */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
jmp L_do_copy
ALIGN 4
L_contiguous_in_window:
mov rsi, [rsp+56] ; /* rsi = window */
add rsi, rax
sub rsi, rcx ; /* from += write - nbytes */
mov eax, r14d ; /* eax = len */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
jmp L_do_copy ; /* if (nbytes >= len) */
ALIGN 4
L_do_copy:
mov ecx, eax ; /* ecx = len */
rep movsb
mov rsi, r8 ; /* move in back to %esi, toss from */
jmp L_while_test
L_test_for_end_of_block:
test al, 32
jz L_invalid_literal_length_code
mov dword ptr [rsp+116], 1
jmp L_break_loop_with_status
L_invalid_literal_length_code:
mov dword ptr [rsp+116], 2
jmp L_break_loop_with_status
L_invalid_distance_code:
mov dword ptr [rsp+116], 3
jmp L_break_loop_with_status
L_invalid_distance_too_far:
mov dword ptr [rsp+116], 4
jmp L_break_loop_with_status
L_break_loop:
mov dword ptr [rsp+116], 0
L_break_loop_with_status:
; /* put in, out, bits, and hold back into ar and pop esp */
mov [rsp+16], rsi ; /* in */
mov [rsp+32], rdi ; /* out */
mov [rsp+88], ebx ; /* bits */
mov [rsp+80], rdx ; /* hold */
mov rax, [rsp] ; /* restore rbp and rsp */
mov rbp, [rsp+8]
mov rsp, rax
mov rsi,[rsp-8]
mov rdi,[rsp-16]
mov r12,[rsp-24]
mov r13,[rsp-32]
mov r14,[rsp-40]
mov r15,[rsp-48]
mov rbx,[rsp-56]
ret 0
; :
; : "m" (ar)
; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
; );
inffas8664fnc ENDP
;_TEXT ENDS
END

View File

@ -0,0 +1,28 @@
Summary
-------
This directory contains ASM implementations of the functions
longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t),
for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits.
gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits
assembly optimized version from Jean-loup Gailly original longest_match function
inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing
original function from Mark Adler
Use instructions
----------------
Copy these files into the zlib source directory.
define ASMV and ASMINF in your project. Include inffas8664.c in your source tree,
and inffasx64.obj and gvmat64.obj as object to link.
Build instructions
------------------
run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe)
ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
You can get Windows 2003 server DDK with ml64 and cl for AMD64 from
http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)

View File

@ -0,0 +1,2 @@
ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm
ml /coff /Zi /c /Flinffas32.lst inffas32.asm

View File

@ -0,0 +1,972 @@
; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
; File written by Gilles Vollant, by modifiying the longest_match
; from Jean-loup Gailly in deflate.c
;
; http://www.zlib.net
; http://www.winimage.com/zLibDll
; http://www.muppetlabs.com/~breadbox/software/assembly.html
;
; For Visual C++ 4.x and higher and ML 6.x and higher
; ml.exe is in directory \MASM611C of Win95 DDK
; ml.exe is also distributed in http://www.masm32.com/masmdl.htm
; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
;
; this file contain two implementation of longest_match
;
; longest_match_7fff : written 1996 by Gilles Vollant optimized for
; first Pentium. Assume s->w_mask == 0x7fff
; longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro
;
; for using an seembly version of longest_match, you need define ASMV in project
; There is two way in using gvmat32.asm
;
; A) Suggested method
; if you want include both longest_match_7fff and longest_match_686
; compile the asm file running
; ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm
; and include gvmat32c.c in your project
; if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,
; longest_match_7fff will be used
; if you have a more modern CPU (Pentium Pro, II and higher)
; longest_match_686 will be used
; on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,
; but this is not a sitation you'll find often
;
; B) Alternative
; if you are not interresed in old cpu performance and want the smaller
; binaries possible
;
; compile the asm file running
; ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm
; and do not include gvmat32c.c in your project (ou define also
; NOOLDPENTIUMCODE)
;
; note : as I known, longest_match_686 is very faster than longest_match_7fff
; on pentium Pro/II/III, faster (but less) in P4, but it seem
; longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8
;
; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2
;uInt longest_match_7fff(s, cur_match)
; deflate_state *s;
; IPos cur_match; /* current match */
NbStack equ 76
cur_match equ dword ptr[esp+NbStack-0]
str_s equ dword ptr[esp+NbStack-4]
; 5 dword on top (ret,ebp,esi,edi,ebx)
adrret equ dword ptr[esp+NbStack-8]
pushebp equ dword ptr[esp+NbStack-12]
pushedi equ dword ptr[esp+NbStack-16]
pushesi equ dword ptr[esp+NbStack-20]
pushebx equ dword ptr[esp+NbStack-24]
chain_length equ dword ptr [esp+NbStack-28]
limit equ dword ptr [esp+NbStack-32]
best_len equ dword ptr [esp+NbStack-36]
window equ dword ptr [esp+NbStack-40]
prev equ dword ptr [esp+NbStack-44]
scan_start equ word ptr [esp+NbStack-48]
wmask equ dword ptr [esp+NbStack-52]
match_start_ptr equ dword ptr [esp+NbStack-56]
nice_match equ dword ptr [esp+NbStack-60]
scan equ dword ptr [esp+NbStack-64]
windowlen equ dword ptr [esp+NbStack-68]
match_start equ dword ptr [esp+NbStack-72]
strend equ dword ptr [esp+NbStack-76]
NbStackAdd equ (NbStack-24)
.386p
name gvmatch
.MODEL FLAT
; all the +zlib1222add offsets are due to the addition of fields
; in zlib in the deflate_state structure since the asm code was first written
; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
zlib1222add equ 8
; Note : these value are good with a 8 bytes boundary pack structure
dep_chain_length equ 74h+zlib1222add
dep_window equ 30h+zlib1222add
dep_strstart equ 64h+zlib1222add
dep_prev_length equ 70h+zlib1222add
dep_nice_match equ 88h+zlib1222add
dep_w_size equ 24h+zlib1222add
dep_prev equ 38h+zlib1222add
dep_w_mask equ 2ch+zlib1222add
dep_good_match equ 84h+zlib1222add
dep_match_start equ 68h+zlib1222add
dep_lookahead equ 6ch+zlib1222add
_TEXT segment
IFDEF NOUNDERLINE
IFDEF NOOLDPENTIUMCODE
public longest_match
public match_init
ELSE
public longest_match_7fff
public cpudetect32
public longest_match_686
ENDIF
ELSE
IFDEF NOOLDPENTIUMCODE
public _longest_match
public _match_init
ELSE
public _longest_match_7fff
public _cpudetect32
public _longest_match_686
ENDIF
ENDIF
MAX_MATCH equ 258
MIN_MATCH equ 3
MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
IFNDEF NOOLDPENTIUMCODE
IFDEF NOUNDERLINE
longest_match_7fff proc near
ELSE
_longest_match_7fff proc near
ENDIF
mov edx,[esp+4]
push ebp
push edi
push esi
push ebx
sub esp,NbStackAdd
; initialize or check the variables used in match.asm.
mov ebp,edx
; chain_length = s->max_chain_length
; if (prev_length>=good_match) chain_length >>= 2
mov edx,[ebp+dep_chain_length]
mov ebx,[ebp+dep_prev_length]
cmp [ebp+dep_good_match],ebx
ja noshr
shr edx,2
noshr:
; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
inc edx
mov edi,[ebp+dep_nice_match]
mov chain_length,edx
mov eax,[ebp+dep_lookahead]
cmp eax,edi
; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
jae nolookaheadnicematch
mov edi,eax
nolookaheadnicematch:
; best_len = s->prev_length
mov best_len,ebx
; window = s->window
mov esi,[ebp+dep_window]
mov ecx,[ebp+dep_strstart]
mov window,esi
mov nice_match,edi
; scan = window + strstart
add esi,ecx
mov scan,esi
; dx = *window
mov dx,word ptr [esi]
; bx = *(window+best_len-1)
mov bx,word ptr [esi+ebx-1]
add esi,MAX_MATCH-1
; scan_start = *scan
mov scan_start,dx
; strend = scan + MAX_MATCH-1
mov strend,esi
; bx = scan_end = *(window+best_len-1)
; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
; s->strstart - (IPos)MAX_DIST(s) : NIL;
mov esi,[ebp+dep_w_size]
sub esi,MIN_LOOKAHEAD
; here esi = MAX_DIST(s)
sub ecx,esi
ja nodist
xor ecx,ecx
nodist:
mov limit,ecx
; prev = s->prev
mov edx,[ebp+dep_prev]
mov prev,edx
;
mov edx,dword ptr [ebp+dep_match_start]
mov bp,scan_start
mov eax,cur_match
mov match_start,edx
mov edx,window
mov edi,edx
add edi,best_len
mov esi,prev
dec edi
; windowlen = window + best_len -1
mov windowlen,edi
jmp beginloop2
align 4
; here, in the loop
; eax = ax = cur_match
; ecx = limit
; bx = scan_end
; bp = scan_start
; edi = windowlen (window + best_len -1)
; esi = prev
;// here; chain_length <=16
normalbeg0add16:
add chain_length,16
jz exitloop
normalbeg0:
cmp word ptr[edi+eax],bx
je normalbeg2noroll
rcontlabnoroll:
; cur_match = prev[cur_match & wmask]
and eax,7fffh
mov ax,word ptr[esi+eax*2]
; if cur_match > limit, go to exitloop
cmp ecx,eax
jnb exitloop
; if --chain_length != 0, go to exitloop
dec chain_length
jnz normalbeg0
jmp exitloop
normalbeg2noroll:
; if (scan_start==*(cur_match+window)) goto normalbeg2
cmp bp,word ptr[edx+eax]
jne rcontlabnoroll
jmp normalbeg2
contloop3:
mov edi,windowlen
; cur_match = prev[cur_match & wmask]
and eax,7fffh
mov ax,word ptr[esi+eax*2]
; if cur_match > limit, go to exitloop
cmp ecx,eax
jnbexitloopshort1:
jnb exitloop
; if --chain_length != 0, go to exitloop
; begin the main loop
beginloop2:
sub chain_length,16+1
; if chain_length <=16, don't use the unrolled loop
jna normalbeg0add16
do16:
cmp word ptr[edi+eax],bx
je normalbeg2dc0
maccn MACRO lab
and eax,7fffh
mov ax,word ptr[esi+eax*2]
cmp ecx,eax
jnb exitloop
cmp word ptr[edi+eax],bx
je lab
ENDM
rcontloop0:
maccn normalbeg2dc1
rcontloop1:
maccn normalbeg2dc2
rcontloop2:
maccn normalbeg2dc3
rcontloop3:
maccn normalbeg2dc4
rcontloop4:
maccn normalbeg2dc5
rcontloop5:
maccn normalbeg2dc6
rcontloop6:
maccn normalbeg2dc7
rcontloop7:
maccn normalbeg2dc8
rcontloop8:
maccn normalbeg2dc9
rcontloop9:
maccn normalbeg2dc10
rcontloop10:
maccn short normalbeg2dc11
rcontloop11:
maccn short normalbeg2dc12
rcontloop12:
maccn short normalbeg2dc13
rcontloop13:
maccn short normalbeg2dc14
rcontloop14:
maccn short normalbeg2dc15
rcontloop15:
and eax,7fffh
mov ax,word ptr[esi+eax*2]
cmp ecx,eax
jnb exitloop
sub chain_length,16
ja do16
jmp normalbeg0add16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
normbeg MACRO rcontlab,valsub
; if we are here, we know that *(match+best_len-1) == scan_end
cmp bp,word ptr[edx+eax]
; if (match != scan_start) goto rcontlab
jne rcontlab
; calculate the good chain_length, and we'll compare scan and match string
add chain_length,16-valsub
jmp iseq
ENDM
normalbeg2dc11:
normbeg rcontloop11,11
normalbeg2dc12:
normbeg short rcontloop12,12
normalbeg2dc13:
normbeg short rcontloop13,13
normalbeg2dc14:
normbeg short rcontloop14,14
normalbeg2dc15:
normbeg short rcontloop15,15
normalbeg2dc10:
normbeg rcontloop10,10
normalbeg2dc9:
normbeg rcontloop9,9
normalbeg2dc8:
normbeg rcontloop8,8
normalbeg2dc7:
normbeg rcontloop7,7
normalbeg2dc6:
normbeg rcontloop6,6
normalbeg2dc5:
normbeg rcontloop5,5
normalbeg2dc4:
normbeg rcontloop4,4
normalbeg2dc3:
normbeg rcontloop3,3
normalbeg2dc2:
normbeg rcontloop2,2
normalbeg2dc1:
normbeg rcontloop1,1
normalbeg2dc0:
normbeg rcontloop0,0
; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
normalbeg2:
mov edi,window
cmp bp,word ptr[edi+eax]
jne contloop3 ; if *(ushf*)match != scan_start, continue
iseq:
; if we are here, we know that *(match+best_len-1) == scan_end
; and (match == scan_start)
mov edi,edx
mov esi,scan ; esi = scan
add edi,eax ; edi = window + cur_match = match
mov edx,[esi+3] ; compare manually dword at match+3
xor edx,[edi+3] ; and scan +3
jz begincompare ; if equal, go to long compare
; we will determine the unmatch byte and calculate len (in esi)
or dl,dl
je eq1rr
mov esi,3
jmp trfinval
eq1rr:
or dx,dx
je eq1
mov esi,4
jmp trfinval
eq1:
and edx,0ffffffh
jz eq11
mov esi,5
jmp trfinval
eq11:
mov esi,6
jmp trfinval
begincompare:
; here we now scan and match begin same
add edi,6
add esi,6
mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes
repe cmpsd ; loop until mismatch
je trfin ; go to trfin if not unmatch
; we determine the unmatch byte
sub esi,4
mov edx,[edi-4]
xor edx,[esi]
or dl,dl
jnz trfin
inc esi
or dx,dx
jnz trfin
inc esi
and edx,0ffffffh
jnz trfin
inc esi
trfin:
sub esi,scan ; esi = len
trfinval:
; here we have finised compare, and esi contain len of equal string
cmp esi,best_len ; if len > best_len, go newbestlen
ja short newbestlen
; now we restore edx, ecx and esi, for the big loop
mov esi,prev
mov ecx,limit
mov edx,window
jmp contloop3
newbestlen:
mov best_len,esi ; len become best_len
mov match_start,eax ; save new position as match_start
cmp esi,nice_match ; if best_len >= nice_match, exit
jae exitloop
mov ecx,scan
mov edx,window ; restore edx=window
add ecx,esi
add esi,edx
dec esi
mov windowlen,esi ; windowlen = window + best_len-1
mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end
; now we restore ecx and esi, for the big loop :
mov esi,prev
mov ecx,limit
jmp contloop3
exitloop:
; exit : s->match_start=match_start
mov ebx,match_start
mov ebp,str_s
mov ecx,best_len
mov dword ptr [ebp+dep_match_start],ebx
mov eax,dword ptr [ebp+dep_lookahead]
cmp ecx,eax
ja minexlo
mov eax,ecx
minexlo:
; return min(best_len,s->lookahead)
; restore stack and register ebx,esi,edi,ebp
add esp,NbStackAdd
pop ebx
pop esi
pop edi
pop ebp
ret
InfoAuthor:
; please don't remove this string !
; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
IFDEF NOUNDERLINE
longest_match_7fff endp
ELSE
_longest_match_7fff endp
ENDIF
IFDEF NOUNDERLINE
cpudetect32 proc near
ELSE
_cpudetect32 proc near
ENDIF
push ebx
pushfd ; push original EFLAGS
pop eax ; get original EFLAGS
mov ecx, eax ; save original EFLAGS
xor eax, 40000h ; flip AC bit in EFLAGS
push eax ; save new EFLAGS value on stack
popfd ; replace current EFLAGS value
pushfd ; get new EFLAGS
pop eax ; store new EFLAGS in EAX
xor eax, ecx ; cant toggle AC bit, processor=80386
jz end_cpu_is_386 ; jump if 80386 processor
push ecx
popfd ; restore AC bit in EFLAGS first
pushfd
pushfd
pop ecx
mov eax, ecx ; get original EFLAGS
xor eax, 200000h ; flip ID bit in EFLAGS
push eax ; save new EFLAGS value on stack
popfd ; replace current EFLAGS value
pushfd ; get new EFLAGS
pop eax ; store new EFLAGS in EAX
popfd ; restore original EFLAGS
xor eax, ecx ; cant toggle ID bit,
je is_old_486 ; processor=old
mov eax,1
db 0fh,0a2h ;CPUID
exitcpudetect:
pop ebx
ret
end_cpu_is_386:
mov eax,0300h
jmp exitcpudetect
is_old_486:
mov eax,0400h
jmp exitcpudetect
IFDEF NOUNDERLINE
cpudetect32 endp
ELSE
_cpudetect32 endp
ENDIF
ENDIF
MAX_MATCH equ 258
MIN_MATCH equ 3
MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1)
MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h)
;;; stack frame offsets
chainlenwmask equ esp + 0 ; high word: current chain len
; low word: s->wmask
window equ esp + 4 ; local copy of s->window
windowbestlen equ esp + 8 ; s->window + bestlen
scanstart equ esp + 16 ; first two bytes of string
scanend equ esp + 12 ; last two bytes of string
scanalign equ esp + 20 ; dword-misalignment of string
nicematch equ esp + 24 ; a good enough match size
bestlen equ esp + 28 ; size of best match so far
scan equ esp + 32 ; ptr to string wanting match
LocalVarsSize equ 36
; saved ebx byte esp + 36
; saved edi byte esp + 40
; saved esi byte esp + 44
; saved ebp byte esp + 48
; return address byte esp + 52
deflatestate equ esp + 56 ; the function arguments
curmatch equ esp + 60
;;; Offsets for fields in the deflate_state structure. These numbers
;;; are calculated from the definition of deflate_state, with the
;;; assumption that the compiler will dword-align the fields. (Thus,
;;; changing the definition of deflate_state could easily cause this
;;; program to crash horribly, without so much as a warning at
;;; compile time. Sigh.)
dsWSize equ 36+zlib1222add
dsWMask equ 44+zlib1222add
dsWindow equ 48+zlib1222add
dsPrev equ 56+zlib1222add
dsMatchLen equ 88+zlib1222add
dsPrevMatch equ 92+zlib1222add
dsStrStart equ 100+zlib1222add
dsMatchStart equ 104+zlib1222add
dsLookahead equ 108+zlib1222add
dsPrevLen equ 112+zlib1222add
dsMaxChainLen equ 116+zlib1222add
dsGoodMatch equ 132+zlib1222add
dsNiceMatch equ 136+zlib1222add
;;; match.asm -- Pentium-Pro-optimized version of longest_match()
;;; Written for zlib 1.1.2
;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
;;;
;;; This is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License.
;GLOBAL _longest_match, _match_init
;SECTION .text
;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
;_longest_match:
IFDEF NOOLDPENTIUMCODE
IFDEF NOUNDERLINE
longest_match proc near
ELSE
_longest_match proc near
ENDIF
ELSE
IFDEF NOUNDERLINE
longest_match_686 proc near
ELSE
_longest_match_686 proc near
ENDIF
ENDIF
;;; Save registers that the compiler may be using, and adjust esp to
;;; make room for our stack frame.
push ebp
push edi
push esi
push ebx
sub esp, LocalVarsSize
;;; Retrieve the function arguments. ecx will hold cur_match
;;; throughout the entire function. edx will hold the pointer to the
;;; deflate_state structure during the function's setup (before
;;; entering the main loop.
mov edx, [deflatestate]
mov ecx, [curmatch]
;;; uInt wmask = s->w_mask;
;;; unsigned chain_length = s->max_chain_length;
;;; if (s->prev_length >= s->good_match) {
;;; chain_length >>= 2;
;;; }
mov eax, [edx + dsPrevLen]
mov ebx, [edx + dsGoodMatch]
cmp eax, ebx
mov eax, [edx + dsWMask]
mov ebx, [edx + dsMaxChainLen]
jl LastMatchGood
shr ebx, 2
LastMatchGood:
;;; chainlen is decremented once beforehand so that the function can
;;; use the sign flag instead of the zero flag for the exit test.
;;; It is then shifted into the high word, to make room for the wmask
;;; value, which it will always accompany.
dec ebx
shl ebx, 16
or ebx, eax
mov [chainlenwmask], ebx
;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
mov eax, [edx + dsNiceMatch]
mov ebx, [edx + dsLookahead]
cmp ebx, eax
jl LookaheadLess
mov ebx, eax
LookaheadLess: mov [nicematch], ebx
;;; register Bytef *scan = s->window + s->strstart;
mov esi, [edx + dsWindow]
mov [window], esi
mov ebp, [edx + dsStrStart]
lea edi, [esi + ebp]
mov [scan], edi
;;; Determine how many bytes the scan ptr is off from being
;;; dword-aligned.
mov eax, edi
neg eax
and eax, 3
mov [scanalign], eax
;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
;;; s->strstart - (IPos)MAX_DIST(s) : NIL;
mov eax, [edx + dsWSize]
sub eax, MIN_LOOKAHEAD
sub ebp, eax
jg LimitPositive
xor ebp, ebp
LimitPositive:
;;; int best_len = s->prev_length;
mov eax, [edx + dsPrevLen]
mov [bestlen], eax
;;; Store the sum of s->window + best_len in esi locally, and in esi.
add esi, eax
mov [windowbestlen], esi
;;; register ush scan_start = *(ushf*)scan;
;;; register ush scan_end = *(ushf*)(scan+best_len-1);
;;; Posf *prev = s->prev;
movzx ebx, word ptr [edi]
mov [scanstart], ebx
movzx ebx, word ptr [edi + eax - 1]
mov [scanend], ebx
mov edi, [edx + dsPrev]
;;; Jump into the main loop.
mov edx, [chainlenwmask]
jmp short LoopEntry
align 4
;;; do {
;;; match = s->window + cur_match;
;;; if (*(ushf*)(match+best_len-1) != scan_end ||
;;; *(ushf*)match != scan_start) continue;
;;; [...]
;;; } while ((cur_match = prev[cur_match & wmask]) > limit
;;; && --chain_length != 0);
;;;
;;; Here is the inner loop of the function. The function will spend the
;;; majority of its time in this loop, and majority of that time will
;;; be spent in the first ten instructions.
;;;
;;; Within this loop:
;;; ebx = scanend
;;; ecx = curmatch
;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
;;; esi = windowbestlen - i.e., (window + bestlen)
;;; edi = prev
;;; ebp = limit
LookupLoop:
and ecx, edx
movzx ecx, word ptr [edi + ecx*2]
cmp ecx, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry: movzx eax, word ptr [esi + ecx - 1]
cmp eax, ebx
jnz LookupLoop
mov eax, [window]
movzx eax, word ptr [eax + ecx]
cmp eax, [scanstart]
jnz LookupLoop
;;; Store the current value of chainlen.
mov [chainlenwmask], edx
;;; Point edi to the string under scrutiny, and esi to the string we
;;; are hoping to match it up with. In actuality, esi and edi are
;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
;;; initialized to -(MAX_MATCH_8 - scanalign).
mov esi, [window]
mov edi, [scan]
add esi, ecx
mov eax, [scanalign]
mov edx, 0fffffef8h; -(MAX_MATCH_8)
lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]
lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]
;;; Test the strings for equality, 8 bytes at a time. At the end,
;;; adjust edx so that it is offset to the exact byte that mismatched.
;;;
;;; We already know at this point that the first three bytes of the
;;; strings match each other, and they can be safely passed over before
;;; starting the compare loop. So what this code does is skip over 0-3
;;; bytes, as much as necessary in order to dword-align the edi
;;; pointer. (esi will still be misaligned three times out of four.)
;;;
;;; It should be confessed that this loop usually does not represent
;;; much of the total running time. Replacing it with a more
;;; straightforward "rep cmpsb" would not drastically degrade
;;; performance.
LoopCmps:
mov eax, [esi + edx]
xor eax, [edi + edx]
jnz LeaveLoopCmps
mov eax, [esi + edx + 4]
xor eax, [edi + edx + 4]
jnz LeaveLoopCmps4
add edx, 8
jnz LoopCmps
jmp short LenMaximum
LeaveLoopCmps4: add edx, 4
LeaveLoopCmps: test eax, 0000FFFFh
jnz LenLower
add edx, 2
shr eax, 16
LenLower: sub al, 1
adc edx, 0
;;; Calculate the length of the match. If it is longer than MAX_MATCH,
;;; then automatically accept it as the best possible match and leave.
lea eax, [edi + edx]
mov edi, [scan]
sub eax, edi
cmp eax, MAX_MATCH
jge LenMaximum
;;; If the length of the match is not longer than the best match we
;;; have so far, then forget it and return to the lookup loop.
mov edx, [deflatestate]
mov ebx, [bestlen]
cmp eax, ebx
jg LongerMatch
mov esi, [windowbestlen]
mov edi, [edx + dsPrev]
mov ebx, [scanend]
mov edx, [chainlenwmask]
jmp LookupLoop
;;; s->match_start = cur_match;
;;; best_len = len;
;;; if (len >= nice_match) break;
;;; scan_end = *(ushf*)(scan+best_len-1);
LongerMatch: mov ebx, [nicematch]
mov [bestlen], eax
mov [edx + dsMatchStart], ecx
cmp eax, ebx
jge LeaveNow
mov esi, [window]
add esi, eax
mov [windowbestlen], esi
movzx ebx, word ptr [edi + eax - 1]
mov edi, [edx + dsPrev]
mov [scanend], ebx
mov edx, [chainlenwmask]
jmp LookupLoop
;;; Accept the current string, with the maximum possible length.
LenMaximum: mov edx, [deflatestate]
mov dword ptr [bestlen], MAX_MATCH
mov [edx + dsMatchStart], ecx
;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
;;; return s->lookahead;
LeaveNow:
mov edx, [deflatestate]
mov ebx, [bestlen]
mov eax, [edx + dsLookahead]
cmp ebx, eax
jg LookaheadRet
mov eax, ebx
LookaheadRet:
;;; Restore the stack and return from whence we came.
add esp, LocalVarsSize
pop ebx
pop esi
pop edi
pop ebp
ret
; please don't remove this string !
; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
IFDEF NOOLDPENTIUMCODE
IFDEF NOUNDERLINE
longest_match endp
ELSE
_longest_match endp
ENDIF
IFDEF NOUNDERLINE
match_init proc near
ret
match_init endp
ELSE
_match_init proc near
ret
_match_init endp
ENDIF
ELSE
IFDEF NOUNDERLINE
longest_match_686 endp
ELSE
_longest_match_686 endp
ENDIF
ENDIF
_TEXT ends
end

View File

@ -0,0 +1,62 @@
/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
* Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
* File written by Gilles Vollant, by modifiying the longest_match
* from Jean-loup Gailly in deflate.c
* it prepare all parameters and call the assembly longest_match_gvasm
* longest_match execute standard C code is wmask != 0x7fff
* (assembly code is faster with a fixed wmask)
*
* Read comment at beginning of gvmat32.asm for more information
*/
#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))
#include "deflate.h"
/* if your C compiler don't add underline before function name,
define ADD_UNDERLINE_ASMFUNC */
#ifdef ADD_UNDERLINE_ASMFUNC
#define longest_match_7fff _longest_match_7fff
#define longest_match_686 _longest_match_686
#define cpudetect32 _cpudetect32
#endif
unsigned long cpudetect32();
uInt longest_match_c(
deflate_state *s,
IPos cur_match); /* current match */
uInt longest_match_7fff(
deflate_state *s,
IPos cur_match); /* current match */
uInt longest_match_686(
deflate_state *s,
IPos cur_match); /* current match */
static uInt iIsPPro=2;
void match_init ()
{
iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
}
uInt longest_match(
deflate_state *s,
IPos cur_match) /* current match */
{
if (iIsPPro!=0)
return longest_match_686(s,cur_match);
if (s->w_mask != 0x7fff)
return longest_match_686(s,cur_match);
/* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */
return longest_match_7fff(s,cur_match);
}
#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
cl /DASMV /I..\.. /O2 /c gvmat32c.c
ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm
ml /coff /Zi /c /Flinffas32.lst inffas32.asm

View File

@ -0,0 +1,21 @@
Summary
-------
This directory contains ASM implementations of the functions
longest_match() and inflate_fast().
Use instructions
----------------
Copy these files into the zlib source directory, then run the
appropriate makefile, as suggested below.
Build instructions
------------------
* With Microsoft C and MASM:
nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="gvmat32c.obj gvmat32.obj inffas32.obj"
* With Borland C and TASM:
make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="gvmat32c.obj gvmat32.obj inffas32.obj" OBJPA="+gvmat32c.obj+gvmat32.obj+inffas32.obj"

View File

@ -0,0 +1,423 @@
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
* tables for updating the shift register in one step with three exclusive-ors
* instead of four steps with four exclusive-ors. This results in about a
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
*/
/* @(#) $Id$ */
/*
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
protection on the static variables used to control the first-use generation
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
*/
#ifdef MAKECRCH
# include <stdio.h>
# ifndef DYNAMIC_CRC_TABLE
# define DYNAMIC_CRC_TABLE
# endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */
#include "zutil.h" /* for STDC and FAR definitions */
#define local static
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
#ifndef NOBYFOUR
# ifdef STDC /* need ANSI C limits.h to determine sizes */
# include <limits.h>
# define BYFOUR
# if (UINT_MAX == 0xffffffffUL)
typedef unsigned int u4;
# else
# if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long u4;
# else
# if (USHRT_MAX == 0xffffffffUL)
typedef unsigned short u4;
# else
# undef BYFOUR /* can't find a four-byte integer type! */
# endif
# endif
# endif
# endif /* STDC */
#endif /* !NOBYFOUR */
/* Definitions for doing the crc four data bytes at a time. */
#ifdef BYFOUR
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
local unsigned long crc32_little OF((unsigned long,
const unsigned char FAR *, unsigned));
local unsigned long crc32_big OF((unsigned long,
const unsigned char FAR *, unsigned));
# define TBLS 8
#else
# define TBLS 1
#endif /* BYFOUR */
/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
#ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1;
local unsigned long FAR crc_table[TBLS][256];
local void make_crc_table OF((void));
#ifdef MAKECRCH
local void write_table OF((FILE *, const unsigned long FAR *));
#endif /* MAKECRCH */
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
Polynomials over GF(2) are represented in binary, one bit per coefficient,
with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.
This calculation is done using the shift-register method of multiplying and
taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
x (which is shifting right by one and adding x^32 mod p if the bit shifted
out is a one). We start with the highest power (least significant bit) of
q and repeat for all eight bits of q.
The first table is simply the CRC of all possible eight bit values. This is
all the information needed to generate CRCs on data a byte at a time for all
combinations of CRC register values and incoming bytes. The remaining tables
allow for word-at-a-time CRC calculation for both big-endian and little-
endian machines, where a word is four bytes.
*/
local void make_crc_table()
{
unsigned long c;
int n, k;
unsigned long poly; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */
static volatile int first = 1; /* flag to limit concurrent making */
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
/* See if another task is already doing this (not thread-safe, but better
than nothing -- significantly reduces duration of vulnerability in
case the advice about DYNAMIC_CRC_TABLE is ignored) */
if (first) {
first = 0;
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
poly = 0UL;
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
poly |= 1UL << (31 - p[n]);
/* generate a crc for every 8-bit value */
for (n = 0; n < 256; n++) {
c = (unsigned long)n;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
crc_table[0][n] = c;
}
#ifdef BYFOUR
/* generate crc for each value followed by one, two, and three zeros,
and then the byte reversal of those as well as the first table */
for (n = 0; n < 256; n++) {
c = crc_table[0][n];
crc_table[4][n] = REV(c);
for (k = 1; k < 4; k++) {
c = crc_table[0][c & 0xff] ^ (c >> 8);
crc_table[k][n] = c;
crc_table[k + 4][n] = REV(c);
}
}
#endif /* BYFOUR */
crc_table_empty = 0;
}
else { /* not first */
/* wait for the other guy to finish (not efficient, but rare) */
while (crc_table_empty)
;
}
#ifdef MAKECRCH
/* write out CRC tables to crc32.h */
{
FILE *out;
out = fopen("crc32.h", "w");
if (out == NULL) return;
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
fprintf(out, "local const unsigned long FAR ");
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
write_table(out, crc_table[0]);
# ifdef BYFOUR
fprintf(out, "#ifdef BYFOUR\n");
for (k = 1; k < 8; k++) {
fprintf(out, " },\n {\n");
write_table(out, crc_table[k]);
}
fprintf(out, "#endif\n");
# endif /* BYFOUR */
fprintf(out, " }\n};\n");
fclose(out);
}
#endif /* MAKECRCH */
}
#ifdef MAKECRCH
local void write_table(out, table)
FILE *out;
const unsigned long FAR *table;
{
int n;
for (n = 0; n < 256; n++)
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
}
#endif /* MAKECRCH */
#else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
*/
#include "crc32.h"
#endif /* DYNAMIC_CRC_TABLE */
/* =========================================================================
* This function can be used by asm versions of crc32()
*/
const unsigned long FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
return (const unsigned long FAR *)crc_table;
}
/* ========================================================================= */
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
/* ========================================================================= */
unsigned long ZEXPORT crc32(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
if (buf == Z_NULL) return 0UL;
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
#ifdef BYFOUR
if (sizeof(void *) == sizeof(ptrdiff_t)) {
u4 endian;
endian = 1;
if (*((unsigned char *)(&endian)))
return crc32_little(crc, buf, len);
else
return crc32_big(crc, buf, len);
}
#endif /* BYFOUR */
crc = crc ^ 0xffffffffUL;
while (len >= 8) {
DO8;
len -= 8;
}
if (len) do {
DO1;
} while (--len);
return crc ^ 0xffffffffUL;
}
#ifdef BYFOUR
/* ========================================================================= */
#define DOLIT4 c ^= *buf4++; \
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
/* ========================================================================= */
local unsigned long crc32_little(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register u4 c;
register const u4 FAR *buf4;
c = (u4)crc;
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
len--;
}
buf4 = (const u4 FAR *)(const void FAR *)buf;
while (len >= 32) {
DOLIT32;
len -= 32;
}
while (len >= 4) {
DOLIT4;
len -= 4;
}
buf = (const unsigned char FAR *)buf4;
if (len) do {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
} while (--len);
c = ~c;
return (unsigned long)c;
}
/* ========================================================================= */
#define DOBIG4 c ^= *++buf4; \
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
/* ========================================================================= */
local unsigned long crc32_big(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register u4 c;
register const u4 FAR *buf4;
c = REV((u4)crc);
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
len--;
}
buf4 = (const u4 FAR *)(const void FAR *)buf;
buf4--;
while (len >= 32) {
DOBIG32;
len -= 32;
}
while (len >= 4) {
DOBIG4;
len -= 4;
}
buf4++;
buf = (const unsigned char FAR *)buf4;
if (len) do {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
} while (--len);
c = ~c;
return (unsigned long)(REV(c));
}
#endif /* BYFOUR */
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
/* ========================================================================= */
local unsigned long gf2_matrix_times(mat, vec)
unsigned long *mat;
unsigned long vec;
{
unsigned long sum;
sum = 0;
while (vec) {
if (vec & 1)
sum ^= *mat;
vec >>= 1;
mat++;
}
return sum;
}
/* ========================================================================= */
local void gf2_matrix_square(square, mat)
unsigned long *square;
unsigned long *mat;
{
int n;
for (n = 0; n < GF2_DIM; n++)
square[n] = gf2_matrix_times(mat, mat[n]);
}
/* ========================================================================= */
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off_t len2;
{
int n;
unsigned long row;
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case */
if (len2 == 0)
return crc1;
/* put operator for one zero bit in odd */
odd[0] = 0xedb88320L; /* CRC-32 polynomial */
row = 1;
for (n = 1; n < GF2_DIM; n++) {
odd[n] = row;
row <<= 1;
}
/* put operator for two zero bits in even */
gf2_matrix_square(even, odd);
/* put operator for four zero bits in odd */
gf2_matrix_square(odd, even);
/* apply len2 zeros to crc1 (first square will put the operator for one
zero byte, eight zero bits, in even) */
do {
/* apply zeros operator for this bit of len2 */
gf2_matrix_square(even, odd);
if (len2 & 1)
crc1 = gf2_matrix_times(even, crc1);
len2 >>= 1;
/* if no more bits set, then done */
if (len2 == 0)
break;
/* another iteration of the loop with odd and even swapped */
gf2_matrix_square(odd, even);
if (len2 & 1)
crc1 = gf2_matrix_times(odd, crc1);
len2 >>= 1;
/* if no more bits set, then done */
} while (len2 != 0);
/* return combined crc */
crc1 ^= crc2;
return crc1;
}

View File

@ -0,0 +1,441 @@
/* crc32.h -- tables for rapid CRC calculation
* Generated automatically by crc32.c
*/
local const unsigned long FAR crc_table[TBLS][256] =
{
{
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
#ifdef BYFOUR
},
{
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
0x9324fd72UL
},
{
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
0xbe9834edUL
},
{
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
0xde0506f1UL
},
{
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
0x8def022dUL
},
{
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
0x72fd2493UL
},
{
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
0xed3498beUL
},
{
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
0xf10605deUL
#endif
}
};

View File

@ -0,0 +1,132 @@
/* crypt.h -- base code for crypt/uncrypt ZIPfile
Version 1.00, September 10th, 2003
Copyright (C) 1998-2003 Gilles Vollant
This code is a modified version of crypting code in Infozip distribution
The encryption/decryption parts of this source code (as opposed to the
non-echoing password parts) were originally written in Europe. The
whole source package can be freely distributed, including from the USA.
(Prior to January 2000, re-export from the US was a violation of US law.)
This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).
If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT.
This code support the "Traditional PKWARE Encryption".
The new AES encryption added on Zip format by Winzip (see the page
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
Encryption is not supported.
*/
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/***********************************************************************
* Return the next byte in the pseudo-random sequence
*/
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
/***********************************************************************
* Update the encryption keys with the next byte of plain text
*/
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
{
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{
register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
}
return c;
}
/***********************************************************************
* Initialize the encryption keys and the random header according to
* the given password.
*/
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
{
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L;
while (*passwd != '\0') {
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
passwd++;
}
}
#define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif
static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
const char *passwd; /* password string */
unsigned char *buf; /* where to write header */
int bufSize;
unsigned long* pkeys;
const unsigned long* pcrc_32_tab;
unsigned long crcForCrypting;
{
int n; /* index in random header */
int t; /* temporary */
int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
static unsigned calls = 0; /* ensure different random header each time */
if (bufSize<RAND_HEAD_LEN)
return 0;
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is
* often poorly implemented.
*/
if (++calls == 1)
{
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
}
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
c = (rand() >> 7) & 0xff;
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
}
/* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
}
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
return n;
}
#endif

View File

@ -0,0 +1,623 @@
/* infback.c -- inflate using a call-back interface
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/*
This code is largely copied from inflate.c. Normally either infback.o or
inflate.o would be linked into an application--not both. The interface
with inffast.c is retained so that optimized assembler-coded versions of
inflate_fast() can be used with either inflate.c or infback.c.
*/
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));
/*
strm provides memory allocation functions in zalloc and zfree, or
Z_NULL to use the library memory allocation functions.
windowBits is in the range 8..15, and window is a user-supplied
window and output buffer that is 2**windowBits bytes.
*/
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
z_streamp strm;
int windowBits;
unsigned char FAR *window;
const char *version;
int stream_size;
{
struct inflate_state FAR *state;
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
stream_size != (int)(sizeof(z_stream)))
return Z_VERSION_ERROR;
if (strm == Z_NULL || window == Z_NULL ||
windowBits < 8 || windowBits > 15)
return Z_STREAM_ERROR;
strm->msg = Z_NULL; /* in case we return an error */
if (strm->zalloc == (alloc_func)0) {
strm->zalloc = zcalloc;
strm->opaque = (voidpf)0;
}
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n"));
strm->state = (struct internal_state FAR *)state;
state->dmax = 32768U;
state->wbits = windowBits;
state->wsize = 1U << windowBits;
state->window = window;
state->write = 0;
state->whave = 0;
return Z_OK;
}
/*
Return state with length and distance decoding tables and index sizes set to
fixed code decoding. Normally this returns fixed tables from inffixed.h.
If BUILDFIXED is defined, then instead this routine builds the tables the
first time it's called, and returns those tables the first time and
thereafter. This reduces the size of the code by about 2K bytes, in
exchange for a little execution time. However, BUILDFIXED should not be
used for threaded applications, since the rewriting of the tables and virgin
may not be thread-safe.
*/
local void fixedtables(state)
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED
static int virgin = 1;
static code *lenfix, *distfix;
static code fixed[544];
/* build fixed huffman tables if first call (may not be thread safe) */
if (virgin) {
unsigned sym, bits;
static code *next;
/* literal/length table */
sym = 0;
while (sym < 144) state->lens[sym++] = 8;
while (sym < 256) state->lens[sym++] = 9;
while (sym < 280) state->lens[sym++] = 7;
while (sym < 288) state->lens[sym++] = 8;
next = fixed;
lenfix = next;
bits = 9;
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
/* distance table */
sym = 0;
while (sym < 32) state->lens[sym++] = 5;
distfix = next;
bits = 5;
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
/* do this just once */
virgin = 0;
}
#else /* !BUILDFIXED */
# include "inffixed.h"
#endif /* BUILDFIXED */
state->lencode = lenfix;
state->lenbits = 9;
state->distcode = distfix;
state->distbits = 5;
}
/* Macros for inflateBack(): */
/* Load returned state from inflate_fast() */
#define LOAD() \
do { \
put = strm->next_out; \
left = strm->avail_out; \
next = strm->next_in; \
have = strm->avail_in; \
hold = state->hold; \
bits = state->bits; \
} while (0)
/* Set state from registers for inflate_fast() */
#define RESTORE() \
do { \
strm->next_out = put; \
strm->avail_out = left; \
strm->next_in = next; \
strm->avail_in = have; \
state->hold = hold; \
state->bits = bits; \
} while (0)
/* Clear the input bit accumulator */
#define INITBITS() \
do { \
hold = 0; \
bits = 0; \
} while (0)
/* Assure that some input is available. If input is requested, but denied,
then return a Z_BUF_ERROR from inflateBack(). */
#define PULL() \
do { \
if (have == 0) { \
have = in(in_desc, &next); \
if (have == 0) { \
next = Z_NULL; \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)
/* Get a byte of input into the bit accumulator, or return from inflateBack()
with an error if there is no input available. */
#define PULLBYTE() \
do { \
PULL(); \
have--; \
hold += (unsigned long)(*next++) << bits; \
bits += 8; \
} while (0)
/* Assure that there are at least n bits in the bit accumulator. If there is
not enough available input to do that, then return from inflateBack() with
an error. */
#define NEEDBITS(n) \
do { \
while (bits < (unsigned)(n)) \
PULLBYTE(); \
} while (0)
/* Return the low n bits of the bit accumulator (n < 16) */
#define BITS(n) \
((unsigned)hold & ((1U << (n)) - 1))
/* Remove n bits from the bit accumulator */
#define DROPBITS(n) \
do { \
hold >>= (n); \
bits -= (unsigned)(n); \
} while (0)
/* Remove zero to seven bits as needed to go to a byte boundary */
#define BYTEBITS() \
do { \
hold >>= bits & 7; \
bits -= bits & 7; \
} while (0)
/* Assure that some output space is available, by writing out the window
if it's full. If the write fails, return from inflateBack() with a
Z_BUF_ERROR. */
#define ROOM() \
do { \
if (left == 0) { \
put = state->window; \
left = state->wsize; \
state->whave = left; \
if (out(out_desc, put, left)) { \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)
/*
strm provides the memory allocation functions and window buffer on input,
and provides information on the unused input on return. For Z_DATA_ERROR
returns, strm will also provide an error message.
in() and out() are the call-back input and output functions. When
inflateBack() needs more input, it calls in(). When inflateBack() has
filled the window with output, or when it completes with data in the
window, it calls out() to write out the data. The application must not
change the provided input until in() is called again or inflateBack()
returns. The application must not change the window/output buffer until
inflateBack() returns.
in() and out() are called with a descriptor parameter provided in the
inflateBack() call. This parameter can be a structure that provides the
information required to do the read or write, as well as accumulated
information on the input and output such as totals and check values.
in() should return zero on failure. out() should return non-zero on
failure. If either in() or out() fails, than inflateBack() returns a
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
was in() or out() that caused in the error. Otherwise, inflateBack()
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
error, or Z_MEM_ERROR if it could not allocate memory for the state.
inflateBack() can also return Z_STREAM_ERROR if the input parameters
are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
void FAR *out_desc;
{
struct inflate_state FAR *state;
unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
unsigned bits; /* bits in bit buffer */
unsigned copy; /* number of stored or match bytes to copy */
unsigned char FAR *from; /* where to copy match bytes from */
code this; /* current decoding table entry */
code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */
int ret; /* return code */
static const unsigned short order[19] = /* permutation of code lengths */
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
/* Check that the strm exists and that the state was initialized */
if (strm == Z_NULL || strm->state == Z_NULL)
return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
/* Reset the state */
strm->msg = Z_NULL;
state->mode = TYPE;
state->last = 0;
state->whave = 0;
next = strm->next_in;
have = next != Z_NULL ? strm->avail_in : 0;
hold = 0;
bits = 0;
put = state->window;
left = state->wsize;
/* Inflate until end of block marked as last */
for (;;)
switch (state->mode) {
case TYPE:
/* determine and dispatch block type */
if (state->last) {
BYTEBITS();
state->mode = DONE;
break;
}
NEEDBITS(3);
state->last = BITS(1);
DROPBITS(1);
switch (BITS(2)) {
case 0: /* stored block */
Tracev((stderr, "inflate: stored block%s\n",
state->last ? " (last)" : ""));
state->mode = STORED;
break;
case 1: /* fixed block */
fixedtables(state);
Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : ""));
state->mode = LEN; /* decode codes */
break;
case 2: /* dynamic block */
Tracev((stderr, "inflate: dynamic codes block%s\n",
state->last ? " (last)" : ""));
state->mode = TABLE;
break;
case 3:
strm->msg = (char *)"invalid block type";
state->mode = BAD;
}
DROPBITS(2);
break;
case STORED:
/* get and verify stored block length */
BYTEBITS(); /* go to byte boundary */
NEEDBITS(32);
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
strm->msg = (char *)"invalid stored block lengths";
state->mode = BAD;
break;
}
state->length = (unsigned)hold & 0xffff;
Tracev((stderr, "inflate: stored length %u\n",
state->length));
INITBITS();
/* copy stored block from input to output */
while (state->length != 0) {
copy = state->length;
PULL();
ROOM();
if (copy > have) copy = have;
if (copy > left) copy = left;
zmemcpy(put, next, copy);
have -= copy;
next += copy;
left -= copy;
put += copy;
state->length -= copy;
}
Tracev((stderr, "inflate: stored end\n"));
state->mode = TYPE;
break;
case TABLE:
/* get dynamic table entries descriptor */
NEEDBITS(14);
state->nlen = BITS(5) + 257;
DROPBITS(5);
state->ndist = BITS(5) + 1;
DROPBITS(5);
state->ncode = BITS(4) + 4;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if (state->nlen > 286 || state->ndist > 30) {
strm->msg = (char *)"too many length or distance symbols";
state->mode = BAD;
break;
}
#endif
Tracev((stderr, "inflate: table sizes ok\n"));
/* get code length code lengths (not a typo) */
state->have = 0;
while (state->have < state->ncode) {
NEEDBITS(3);
state->lens[order[state->have++]] = (unsigned short)BITS(3);
DROPBITS(3);
}
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid code lengths set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: code lengths ok\n"));
/* get length and distance code code lengths */
state->have = 0;
while (state->have < state->nlen + state->ndist) {
for (;;) {
this = state->lencode[BITS(state->lenbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if (this.val < 16) {
NEEDBITS(this.bits);
DROPBITS(this.bits);
state->lens[state->have++] = this.val;
}
else {
if (this.val == 16) {
NEEDBITS(this.bits + 2);
DROPBITS(this.bits);
if (state->have == 0) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
len = (unsigned)(state->lens[state->have - 1]);
copy = 3 + BITS(2);
DROPBITS(2);
}
else if (this.val == 17) {
NEEDBITS(this.bits + 3);
DROPBITS(this.bits);
len = 0;
copy = 3 + BITS(3);
DROPBITS(3);
}
else {
NEEDBITS(this.bits + 7);
DROPBITS(this.bits);
len = 0;
copy = 11 + BITS(7);
DROPBITS(7);
}
if (state->have + copy > state->nlen + state->ndist) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
while (copy--)
state->lens[state->have++] = (unsigned short)len;
}
}
/* handle error breaks in while */
if (state->mode == BAD) break;
/* build code tables */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid literal/lengths set";
state->mode = BAD;
break;
}
state->distcode = (code const FAR *)(state->next);
state->distbits = 6;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if (ret) {
strm->msg = (char *)"invalid distances set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;
case LEN:
/* use inflate_fast() if we have enough input and output */
if (have >= 6 && left >= 258) {
RESTORE();
if (state->whave < state->wsize)
state->whave = state->wsize - left;
inflate_fast(strm, state->wsize);
LOAD();
break;
}
/* get a literal, length, or end-of-block code */
for (;;) {
this = state->lencode[BITS(state->lenbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if (this.op && (this.op & 0xf0) == 0) {
last = this;
for (;;) {
this = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + this.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(this.bits);
state->length = (unsigned)this.val;
/* process literal */
if (this.op == 0) {
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", this.val));
ROOM();
*put++ = (unsigned char)(state->length);
left--;
state->mode = LEN;
break;
}
/* process end of block */
if (this.op & 32) {
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
/* invalid code */
if (this.op & 64) {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
/* length code -- get extra bits, if any */
state->extra = (unsigned)(this.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->length += BITS(state->extra);
DROPBITS(state->extra);
}
Tracevv((stderr, "inflate: length %u\n", state->length));
/* get distance code */
for (;;) {
this = state->distcode[BITS(state->distbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if ((this.op & 0xf0) == 0) {
last = this;
for (;;) {
this = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + this.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(this.bits);
if (this.op & 64) {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
state->offset = (unsigned)this.val;
/* get distance extra bits, if any */
state->extra = (unsigned)(this.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
}
if (state->offset > state->wsize - (state->whave < state->wsize ?
left : 0)) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
Tracevv((stderr, "inflate: distance %u\n", state->offset));
/* copy match from window to output */
do {
ROOM();
copy = state->wsize - state->offset;
if (copy < left) {
from = put + copy;
copy = left - copy;
}
else {
from = put - state->offset;
copy = left;
}
if (copy > state->length) copy = state->length;
state->length -= copy;
left -= copy;
do {
*put++ = *from++;
} while (--copy);
} while (state->length != 0);
break;
case DONE:
/* inflate stream terminated properly -- write leftover output */
ret = Z_STREAM_END;
if (left < state->wsize) {
if (out(out_desc, state->window, state->wsize - left))
ret = Z_BUF_ERROR;
}
goto inf_leave;
case BAD:
ret = Z_DATA_ERROR;
goto inf_leave;
default: /* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR;
goto inf_leave;
}
/* Return unused input */
inf_leave:
strm->next_in = next;
strm->avail_in = have;
return ret;
}
int ZEXPORT inflateBackEnd(strm)
z_streamp strm;
{
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
ZFREE(strm, strm->state);
strm->state = Z_NULL;
Tracev((stderr, "inflate: end\n"));
return Z_OK;
}

View File

@ -0,0 +1,318 @@
/* inffast.c -- fast decoding
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
#ifndef ASMINF
/* Allow machine dependent optimization for post-increment or pre-increment.
Based on testing to date,
Pre-increment preferred for:
- PowerPC G3 (Adler)
- MIPS R5000 (Randers-Pehrson)
Post-increment preferred for:
- none
No measurable difference:
- Pentium III (Anderson)
- M68060 (Nikl)
*/
#ifdef POSTINC
# define OFF 0
# define PUP(a) *(a)++
#else
# define OFF 1
# define PUP(a) *++(a)
#endif
/*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
available, an end-of-block is encountered, or a data error is encountered.
When large enough input and output buffers are supplied to inflate(), for
example, a 16K input buffer and a 64K output buffer, more than 95% of the
inflate execution time is spent in this routine.
Entry assumptions:
state->mode == LEN
strm->avail_in >= 6
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8
On return, state->mode is one of:
LEN -- ran out of enough output space or enough available input
TYPE -- reached end of block code, inflate() to interpret next block
BAD -- error in block data
Notes:
- The maximum input bits used by a length/distance pair is 15 bits for the
length code, 5 bits for the length extra, 15 bits for the distance code,
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
Therefore if strm->avail_in >= 6, then there is enough input to avoid
checking for available input while decoding.
- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded. inflate_fast()
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
void inflate_fast(strm, start)
z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{
struct inflate_state FAR *state;
unsigned char FAR *in; /* local strm->next_in */
unsigned char FAR *last; /* while in < last, enough input available */
unsigned char FAR *out; /* local strm->next_out */
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
unsigned char FAR *end; /* while out < end, enough space available */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#endif
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
unsigned long hold; /* local strm->hold */
unsigned bits; /* local strm->bits */
code const FAR *lcode; /* local strm->lencode */
code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
code this; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
unsigned dist; /* match distance */
unsigned char FAR *from; /* where to copy match from */
/* copy state to local variables */
state = (struct inflate_state FAR *)strm->state;
in = strm->next_in - OFF;
last = in + (strm->avail_in - 5);
out = strm->next_out - OFF;
beg = out - (start - strm->avail_out);
end = out + (strm->avail_out - 257);
#ifdef INFLATE_STRICT
dmax = state->dmax;
#endif
wsize = state->wsize;
whave = state->whave;
write = state->write;
window = state->window;
hold = state->hold;
bits = state->bits;
lcode = state->lencode;
dcode = state->distcode;
lmask = (1U << state->lenbits) - 1;
dmask = (1U << state->distbits) - 1;
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
do {
if (bits < 15) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
this = lcode[hold & lmask];
dolen:
op = (unsigned)(this.bits);
hold >>= op;
bits -= op;
op = (unsigned)(this.op);
if (op == 0) { /* literal */
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", this.val));
PUP(out) = (unsigned char)(this.val);
}
else if (op & 16) { /* length base */
len = (unsigned)(this.val);
op &= 15; /* number of extra bits */
if (op) {
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
len += (unsigned)hold & ((1U << op) - 1);
hold >>= op;
bits -= op;
}
Tracevv((stderr, "inflate: length %u\n", len));
if (bits < 15) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
this = dcode[hold & dmask];
dodist:
op = (unsigned)(this.bits);
hold >>= op;
bits -= op;
op = (unsigned)(this.op);
if (op & 16) { /* distance base */
dist = (unsigned)(this.val);
op &= 15; /* number of extra bits */
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
}
dist += (unsigned)hold & ((1U << op) - 1);
#ifdef INFLATE_STRICT
if (dist > dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
hold >>= op;
bits -= op;
Tracevv((stderr, "inflate: distance %u\n", dist));
op = (unsigned)(out - beg); /* max distance in output */
if (dist > op) { /* see if copy from window */
op = dist - op; /* distance back in window */
if (op > whave) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
from = window - OFF;
if (write == 0) { /* very common case */
from += wsize - op;
if (op < len) { /* some from window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
else if (write < op) { /* wrap around window */
from += wsize + write - op;
op -= write;
if (op < len) { /* some from end of window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = window - OFF;
if (write < len) { /* some from start of window */
op = write;
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
}
else { /* contiguous in window */
from += write - op;
if (op < len) { /* some from window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
while (len > 2) {
PUP(out) = PUP(from);
PUP(out) = PUP(from);
PUP(out) = PUP(from);
len -= 3;
}
if (len) {
PUP(out) = PUP(from);
if (len > 1)
PUP(out) = PUP(from);
}
}
else {
from = out - dist; /* copy direct from output */
do { /* minimum length is three */
PUP(out) = PUP(from);
PUP(out) = PUP(from);
PUP(out) = PUP(from);
len -= 3;
} while (len > 2);
if (len) {
PUP(out) = PUP(from);
if (len > 1)
PUP(out) = PUP(from);
}
}
}
else if ((op & 64) == 0) { /* 2nd level distance code */
this = dcode[this.val + (hold & ((1U << op) - 1))];
goto dodist;
}
else {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
}
else if ((op & 64) == 0) { /* 2nd level length code */
this = lcode[this.val + (hold & ((1U << op) - 1))];
goto dolen;
}
else if (op & 32) { /* end-of-block */
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
else {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
} while (in < last && out < end);
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
len = bits >> 3;
in -= len;
bits -= len << 3;
hold &= (1U << bits) - 1;
/* update state and return */
strm->next_in = in + OFF;
strm->next_out = out + OFF;
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
strm->avail_out = (unsigned)(out < end ?
257 + (end - out) : 257 - (out - end));
state->hold = hold;
state->bits = bits;
return;
}
/*
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
- Using bit fields for code structure
- Different op definition to avoid & for extra bits (do & for table bits)
- Three separate decoding do-loops for direct, window, and write == 0
- Special case for distance > 1 copies to do overlapped load and store copy
- Explicit branch predictions (based on measured branch probabilities)
- Deferring match copy and interspersed it with decoding subsequent codes
- Swapping literal/length else
- Swapping window/direct else
- Larger unrolled copy loops (three is about right)
- Moving len -= 3 statement into middle of loop
*/
#endif /* !ASMINF */

View File

@ -0,0 +1,11 @@
/* inffast.h -- header to use inffast.c
* Copyright (C) 1995-2003 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
void inflate_fast OF((z_streamp strm, unsigned start));

View File

@ -0,0 +1,94 @@
/* inffixed.h -- table for decoding fixed codes
* Generated automatically by makefixed().
*/
/* WARNING: this file should *not* be used by applications. It
is part of the implementation of the compression library and
is subject to change. Applications should only use zlib.h.
*/
static const code lenfix[512] = {
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
{0,9,255}
};
static const code distfix[32] = {
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
{22,5,193},{64,5,0}
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
/* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* define NO_GZIP when compiling if you want to disable gzip header and
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
the crc code when it is not needed. For shared libraries, gzip decoding
should be left enabled. */
#ifndef NO_GZIP
# define GUNZIP
#endif
/* Possible inflate modes between inflate() calls */
typedef enum {
HEAD, /* i: waiting for magic header */
FLAGS, /* i: waiting for method and flags (gzip) */
TIME, /* i: waiting for modification time (gzip) */
OS, /* i: waiting for extra flags and operating system (gzip) */
EXLEN, /* i: waiting for extra length (gzip) */
EXTRA, /* i: waiting for extra bytes (gzip) */
NAME, /* i: waiting for end of file name (gzip) */
COMMENT, /* i: waiting for end of comment (gzip) */
HCRC, /* i: waiting for header crc (gzip) */
DICTID, /* i: waiting for dictionary check value */
DICT, /* waiting for inflateSetDictionary() call */
TYPE, /* i: waiting for type bits, including last-flag bit */
TYPEDO, /* i: same, but skip check to exit inflate on new block */
STORED, /* i: waiting for stored size (length and complement) */
COPY, /* i/o: waiting for input or output to copy stored block */
TABLE, /* i: waiting for dynamic block table lengths */
LENLENS, /* i: waiting for code length code lengths */
CODELENS, /* i: waiting for length/lit and distance code lengths */
LEN, /* i: waiting for length/lit code */
LENEXT, /* i: waiting for length extra bits */
DIST, /* i: waiting for distance code */
DISTEXT, /* i: waiting for distance extra bits */
MATCH, /* o: waiting for output space to copy string */
LIT, /* o: waiting for output space to write literal */
CHECK, /* i: waiting for 32-bit check value */
LENGTH, /* i: waiting for 32-bit length (gzip) */
DONE, /* finished check, done -- remain here until reset */
BAD, /* got a data error -- remain here until reset */
MEM, /* got an inflate() memory error -- remain here until reset */
SYNC /* looking for synchronization bytes to restart inflate() */
} inflate_mode;
/*
State transitions between above modes -
(most modes can go to the BAD or MEM mode -- not shown for clarity)
Process header:
HEAD -> (gzip) or (zlib)
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
NAME -> COMMENT -> HCRC -> TYPE
(zlib) -> DICTID or TYPE
DICTID -> DICT -> TYPE
Read deflate blocks:
TYPE -> STORED or TABLE or LEN or CHECK
STORED -> COPY -> TYPE
TABLE -> LENLENS -> CODELENS -> LEN
Read deflate codes:
LEN -> LENEXT or LIT or TYPE
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
LIT -> LEN
Process trailer:
CHECK -> LENGTH -> DONE
*/
/* state maintained between inflate() calls. Approximately 7K bytes. */
struct inflate_state {
inflate_mode mode; /* current inflate mode */
int last; /* true if processing last block */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
gz_headerp head; /* where to save gzip header information */
/* sliding window */
unsigned wbits; /* log base 2 of requested window size */
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if needed */
/* bit accumulator */
unsigned long hold; /* input bit accumulator */
unsigned bits; /* number of bits in "in" */
/* for string and stored block copying */
unsigned length; /* literal or length of data to copy */
unsigned offset; /* distance back to copy string from */
/* for table and code decoding */
unsigned extra; /* extra bits needed */
/* fixed and dynamic code tables */
code const FAR *lencode; /* starting table for length/literal codes */
code const FAR *distcode; /* starting table for distance codes */
unsigned lenbits; /* index bits for lencode */
unsigned distbits; /* index bits for distcode */
/* dynamic table building */
unsigned ncode; /* number of code length code lengths */
unsigned nlen; /* number of length code lengths */
unsigned ndist; /* number of distance code lengths */
unsigned have; /* number of code lengths in lens[] */
code FAR *next; /* next available space in codes[] */
unsigned short lens[320]; /* temporary storage for code lengths */
unsigned short work[288]; /* work area for code table building */
code codes[ENOUGH]; /* space for code tables */
};

View File

@ -0,0 +1,329 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
include such an acknowledgment, I would appreciate that you keep this
copyright string in the executable of your product.
*/
/*
Build a set of tables to decode the provided canonical Huffman code.
The code lengths are lens[0..codes-1]. The result starts at *table,
whose indices are 0..2^bits-1. work is a writable array of at least
lens shorts, which is used as a work area. type is the type of code
to be generated, CODES, LENS, or DISTS. On return, zero is success,
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
on return points to the next available entry's address. bits is the
requested root table index bits, and on return it is the actual root
table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code.
*/
int inflate_table(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
unsigned short FAR *work;
{
unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */
unsigned min, max; /* minimum and maximum code lengths */
unsigned root; /* number of index bits for root table */
unsigned curr; /* number of index bits for current table */
unsigned drop; /* code bits to drop for sub-table */
int left; /* number of prefix codes available */
unsigned used; /* code entries in table used */
unsigned huff; /* Huffman code */
unsigned incr; /* for incrementing code, index */
unsigned fill; /* index for replicating entries */
unsigned low; /* low bits for current root entry */
unsigned mask; /* mask for low root bits */
code this; /* table entry for duplication */
code FAR *next; /* next available space in table */
const unsigned short FAR *base; /* base value table to use */
const unsigned short FAR *extra; /* extra bits table to use */
int end; /* use base and extra for symbol > end */
unsigned short count[MAXBITS+1]; /* number of codes of each length */
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 0, 0};
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
28, 28, 29, 29, 64, 64};
/*
Process a set of code lengths to create a canonical Huffman code. The
code lengths are lens[0..codes-1]. Each length corresponds to the
symbols 0..codes-1. The Huffman code is generated by first sorting the
symbols by length from short to long, and retaining the symbol order
for codes with equal lengths. Then the code starts with all zero bits
for the first code of the shortest length, and the codes are integer
increments for the same length, and zeros are appended as the length
increases. For the deflate format, these bits are stored backwards
from their more natural integer increment ordering, and so when the
decoding tables are built in the large loop below, the integer codes
are incremented backwards.
This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure this.
1..MAXBITS is interpreted as that code length. zero means that that
symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length,
creating from that a table of starting indices for each length in the
sorted table, and then entering the symbols in order in the sorted
table. The sorted table is work[], with that space being provided by
the caller.
The length counts are used for other purposes as well, i.e. finding
the minimum and maximum length codes, determining if there are any
codes at all, checking for a valid set of lengths, and looking ahead
at length counts to determine sub-table sizes when building the
decoding tables.
*/
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
for (len = 0; len <= MAXBITS; len++)
count[len] = 0;
for (sym = 0; sym < codes; sym++)
count[lens[sym]]++;
/* bound code lengths, force root to be within code lengths */
root = *bits;
for (max = MAXBITS; max >= 1; max--)
if (count[max] != 0) break;
if (root > max) root = max;
if (max == 0) { /* no symbols to code at all */
this.op = (unsigned char)64; /* invalid code marker */
this.bits = (unsigned char)1;
this.val = (unsigned short)0;
*(*table)++ = this; /* make a table to force an error */
*(*table)++ = this;
*bits = 1;
return 0; /* no symbols, but wait for decoding to report error */
}
for (min = 1; min <= MAXBITS; min++)
if (count[min] != 0) break;
if (root < min) root = min;
/* check for an over-subscribed or incomplete set of lengths */
left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= count[len];
if (left < 0) return -1; /* over-subscribed */
}
if (left > 0 && (type == CODES || max != 1))
return -1; /* incomplete set */
/* generate offsets into symbol table for each length for sorting */
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + count[len];
/* sort symbols by length, by symbol order within each length */
for (sym = 0; sym < codes; sym++)
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
/*
Create and fill in decoding tables. In this loop, the table being
filled is at next and has curr index bits. The code being used is huff
with length len. That code is converted to an index by dropping drop
bits off of the bottom. For codes where len is less than drop + curr,
those top drop + curr - len bits are incremented through all values to
fill the table with replicated entries.
root is the number of index bits for the root table. When len exceeds
root, sub-tables are created pointed to by the root entry with an index
of the low root bits of huff. This is saved in low to check for when a
new sub-table should be started. drop is zero when the root table is
being filled, and drop is root when sub-tables are being filled.
When a new sub-table is needed, it is necessary to look ahead in the
code lengths to determine what size sub-table is needed. The length
counts are used for this, and so count[] is decremented as codes are
entered in the tables.
used keeps track of how many table entries have been allocated from the
provided *table space. It is checked when a LENS table is being made
against the space in *table, ENOUGH, minus the maximum space needed by
the worst case distance code, MAXD. This should never happen, but the
sufficiency of ENOUGH has not been proven exhaustively, hence the check.
This assumes that when type == LENS, bits == 9.
sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This
routine permits incomplete codes, so another loop after this one fills
in the rest of the decoding tables with invalid code markers.
*/
/* set up for code type */
switch (type) {
case CODES:
base = extra = work; /* dummy value--not used */
end = 19;
break;
case LENS:
base = lbase;
base -= 257;
extra = lext;
extra -= 257;
end = 256;
break;
default: /* DISTS */
base = dbase;
extra = dext;
end = -1;
}
/* initialize state for loop */
huff = 0; /* starting code */
sym = 0; /* starting code symbol */
len = min; /* starting code length */
next = *table; /* current table to fill in */
curr = root; /* current table index bits */
drop = 0; /* current bits to drop from code for index */
low = (unsigned)(-1); /* trigger new sub-table when len > root */
used = 1U << root; /* use root table entries */
mask = used - 1; /* mask for comparing low */
/* check available table space */
if (type == LENS && used >= ENOUGH - MAXD)
return 1;
/* process all codes and make table entries */
for (;;) {
/* create table entry */
this.bits = (unsigned char)(len - drop);
if ((int)(work[sym]) < end) {
this.op = (unsigned char)0;
this.val = work[sym];
}
else if ((int)(work[sym]) > end) {
this.op = (unsigned char)(extra[work[sym]]);
this.val = base[work[sym]];
}
else {
this.op = (unsigned char)(32 + 64); /* end of block */
this.val = 0;
}
/* replicate for those indices with low len bits equal to huff */
incr = 1U << (len - drop);
fill = 1U << curr;
min = fill; /* save offset to next table */
do {
fill -= incr;
next[(huff >> drop) + fill] = this;
} while (fill != 0);
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
/* go to next symbol, update count, len */
sym++;
if (--(count[len]) == 0) {
if (len == max) break;
len = lens[work[sym]];
}
/* create new sub-table if needed */
if (len > root && (huff & mask) != low) {
/* if first time, transition to sub-tables */
if (drop == 0)
drop = root;
/* increment past last table */
next += min; /* here min is 1 << curr */
/* determine length of next table */
curr = len - drop;
left = (int)(1 << curr);
while (curr + drop < max) {
left -= count[curr + drop];
if (left <= 0) break;
curr++;
left <<= 1;
}
/* check for enough space */
used += 1U << curr;
if (type == LENS && used >= ENOUGH - MAXD)
return 1;
/* point entry in root table to sub-table */
low = huff & mask;
(*table)[low].op = (unsigned char)curr;
(*table)[low].bits = (unsigned char)root;
(*table)[low].val = (unsigned short)(next - *table);
}
}
/*
Fill in rest of table for incomplete codes. This loop is similar to the
loop above in incrementing huff for table indices. It is assumed that
len is equal to curr + drop, so there is no loop needed to increment
through high index bits. When the current sub-table is filled, the loop
drops back to the root table to fill in any remaining entries there.
*/
this.op = (unsigned char)64; /* invalid code marker */
this.bits = (unsigned char)(len - drop);
this.val = (unsigned short)0;
while (huff != 0) {
/* when done with sub-table, drop back to root table */
if (drop != 0 && (huff & mask) != low) {
drop = 0;
len = root;
next = *table;
this.bits = (unsigned char)len;
}
/* put invalid code marker in table */
next[huff >> drop] = this;
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
}
/* set return parameters */
*table += used;
*bits = root;
return 0;
}

View File

@ -0,0 +1,55 @@
/* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* Structure for decoding tables. Each entry provides either the
information needed to do the operation requested by the code that
indexed that table entry, or it provides a pointer to another
table that indexes more bits of the code. op indicates whether
the entry is a pointer to another table, a literal, a length or
distance, an end-of-block, or an invalid code. For a table
pointer, the low four bits of op is the number of index bits of
that table. For a length or distance, the low four bits of op
is the number of extra bits to get after the code. bits is
the number of bits in this code or part of the code to drop off
of the bit buffer. val is the actual byte to output in the case
of a literal, the base length or distance, or the offset from
the current table to the next table. Each entry is four bytes. */
typedef struct {
unsigned char op; /* operation, extra bits, table bits */
unsigned char bits; /* bits in this part of the code */
unsigned short val; /* offset in table or code value */
} code;
/* op values as set by inflate_table():
00000000 - literal
0000tttt - table link, tttt != 0 is the number of table index bits
0001eeee - length or distance, eeee is the number of extra bits
01100000 - end of block
01000000 - invalid code
*/
/* Maximum size of dynamic tree. The maximum found in a long but non-
exhaustive search was 1444 code structures (852 for length/literals
and 592 for distances, the latter actually the result of an
exhaustive search). The true maximum is not known, but the value
below is more than safe. */
#define ENOUGH 2048
#define MAXD 592
/* Type of code to build for inftable() */
typedef enum {
CODES,
LENS,
DISTS
} codetype;
extern int inflate_table OF((codetype type, unsigned short FAR *lens,
unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work));

View File

@ -0,0 +1,61 @@
/* uncompr.c -- decompress a memory buffer
* Copyright (C) 1995-2003 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
/* ===========================================================================
Decompresses the source buffer into the destination buffer. sourceLen is
the byte length of the source buffer. Upon entry, destLen is the total
size of the destination buffer, which must be large enough to hold the
entire uncompressed data. (The size of the uncompressed data must have
been saved previously by the compressor and transmitted to the decompressor
by some mechanism outside the scope of this compression library.)
Upon exit, destLen is the actual size of the compressed buffer.
This function can be used to decompress a whole file at once if the
input file is mmap'ed.
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted.
*/
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
z_stream stream;
int err;
stream.next_in = (Bytef*)source;
stream.avail_in = (uInt)sourceLen;
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
err = inflateInit(&stream);
if (err != Z_OK) return err;
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
return Z_DATA_ERROR;
return err;
}
*destLen = stream.total_out;
err = inflateEnd(&stream);
return err;
}

View File

@ -0,0 +1,332 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef ZCONF_H
#define ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
*/
#ifdef Z_PREFIX
# define deflateInit_ z_deflateInit_
# define deflate z_deflate
# define deflateEnd z_deflateEnd
# define inflateInit_ z_inflateInit_
# define inflate z_inflate
# define inflateEnd z_inflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateSetDictionary z_deflateSetDictionary
# define deflateCopy z_deflateCopy
# define deflateReset z_deflateReset
# define deflateParams z_deflateParams
# define deflateBound z_deflateBound
# define deflatePrime z_deflatePrime
# define inflateInit2_ z_inflateInit2_
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateCopy z_inflateCopy
# define inflateReset z_inflateReset
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# define uncompress z_uncompress
# define adler32 z_adler32
# define crc32 z_crc32
# define get_crc_table z_get_crc_table
# define zError z_zError
# define alloc_func z_alloc_func
# define free_func z_free_func
# define in_func z_in_func
# define out_func z_out_func
# define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
# define Bytef z_Bytef
# define charf z_charf
# define intf z_intf
# define uIntf z_uIntf
# define uLongf z_uLongf
# define voidpf z_voidpf
# define voidp z_voidp
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32
# endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
# include <sys/types.h> /* for off_t */
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# define z_off_t off_t
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if defined(__OS400__)
# define NO_vsnprintf
#endif
#if defined(__MVS__)
# define NO_vsnprintf
# ifdef FAR
# undef FAR
# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
# pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND")
# pragma map(deflateBound,"DEBND")
# pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI")
# pragma map(compressBound,"CMBND")
# pragma map(inflate_table,"INTABL")
# pragma map(inflate_fast,"INFA")
# pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,318 @@
/* zutil.c -- target dependent utility functions for the compression library
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include "zutil.h"
#ifndef NO_DUMMY_DECL
struct internal_state {int dummy;}; /* for buggy compilers */
#endif
const char * const z_errmsg[10] = {
"need dictionary", /* Z_NEED_DICT 2 */
"stream end", /* Z_STREAM_END 1 */
"", /* Z_OK 0 */
"file error", /* Z_ERRNO (-1) */
"stream error", /* Z_STREAM_ERROR (-2) */
"data error", /* Z_DATA_ERROR (-3) */
"insufficient memory", /* Z_MEM_ERROR (-4) */
"buffer error", /* Z_BUF_ERROR (-5) */
"incompatible version",/* Z_VERSION_ERROR (-6) */
""};
const char * ZEXPORT zlibVersion()
{
return ZLIB_VERSION;
}
uLong ZEXPORT zlibCompileFlags()
{
uLong flags;
flags = 0;
switch (sizeof(uInt)) {
case 2: break;
case 4: flags += 1; break;
case 8: flags += 2; break;
default: flags += 3;
}
switch (sizeof(uLong)) {
case 2: break;
case 4: flags += 1 << 2; break;
case 8: flags += 2 << 2; break;
default: flags += 3 << 2;
}
switch (sizeof(voidpf)) {
case 2: break;
case 4: flags += 1 << 4; break;
case 8: flags += 2 << 4; break;
default: flags += 3 << 4;
}
switch (sizeof(z_off_t)) {
case 2: break;
case 4: flags += 1 << 6; break;
case 8: flags += 2 << 6; break;
default: flags += 3 << 6;
}
#ifdef DEBUG
flags += 1 << 8;
#endif
#if defined(ASMV) || defined(ASMINF)
flags += 1 << 9;
#endif
#ifdef ZLIB_WINAPI
flags += 1 << 10;
#endif
#ifdef BUILDFIXED
flags += 1 << 12;
#endif
#ifdef DYNAMIC_CRC_TABLE
flags += 1 << 13;
#endif
#ifdef NO_GZCOMPRESS
flags += 1L << 16;
#endif
#ifdef NO_GZIP
flags += 1L << 17;
#endif
#ifdef PKZIP_BUG_WORKAROUND
flags += 1L << 20;
#endif
#ifdef FASTEST
flags += 1L << 21;
#endif
#ifdef STDC
# ifdef NO_vsnprintf
flags += 1L << 25;
# ifdef HAS_vsprintf_void
flags += 1L << 26;
# endif
# else
# ifdef HAS_vsnprintf_void
flags += 1L << 26;
# endif
# endif
#else
flags += 1L << 24;
# ifdef NO_snprintf
flags += 1L << 25;
# ifdef HAS_sprintf_void
flags += 1L << 26;
# endif
# else
# ifdef HAS_snprintf_void
flags += 1L << 26;
# endif
# endif
#endif
return flags;
}
#ifdef DEBUG
# ifndef verbose
# define verbose 0
# endif
int z_verbose = verbose;
void z_error (m)
char *m;
{
fprintf(stderr, "%s\n", m);
exit(1);
}
#endif
/* exported to allow conversion of error code to string for compress() and
* uncompress()
*/
const char * ZEXPORT zError(err)
int err;
{
return ERR_MSG(err);
}
#if defined(_WIN32_WCE)
/* The Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used.
*/
int errno = 0;
#endif
#ifndef HAVE_MEMCPY
void zmemcpy(dest, source, len)
Bytef* dest;
const Bytef* source;
uInt len;
{
if (len == 0) return;
do {
*dest++ = *source++; /* ??? to be unrolled */
} while (--len != 0);
}
int zmemcmp(s1, s2, len)
const Bytef* s1;
const Bytef* s2;
uInt len;
{
uInt j;
for (j = 0; j < len; j++) {
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
}
return 0;
}
void zmemzero(dest, len)
Bytef* dest;
uInt len;
{
if (len == 0) return;
do {
*dest++ = 0; /* ??? to be unrolled */
} while (--len != 0);
}
#endif
#ifdef SYS16BIT
#ifdef __TURBOC__
/* Turbo C in 16-bit mode */
# define MY_ZCALLOC
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
* and farmalloc(64K) returns a pointer with an offset of 8, so we
* must fix the pointer. Warning: the pointer must be put back to its
* original form in order to free it, use zcfree().
*/
#define MAX_PTR 10
/* 10*64K = 640K */
local int next_ptr = 0;
typedef struct ptr_table_s {
voidpf org_ptr;
voidpf new_ptr;
} ptr_table;
local ptr_table table[MAX_PTR];
/* This table is used to remember the original form of pointers
* to large buffers (64K). Such pointers are normalized with a zero offset.
* Since MSDOS is not a preemptive multitasking OS, this table is not
* protected from concurrent access. This hack doesn't work anyway on
* a protected system like OS/2. Use Microsoft C instead.
*/
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
voidpf buf = opaque; /* just to make some compilers happy */
ulg bsize = (ulg)items*size;
/* If we allocate less than 65520 bytes, we assume that farmalloc
* will return a usable pointer which doesn't have to be normalized.
*/
if (bsize < 65520L) {
buf = farmalloc(bsize);
if (*(ush*)&buf != 0) return buf;
} else {
buf = farmalloc(bsize + 16L);
}
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
table[next_ptr].org_ptr = buf;
/* Normalize the pointer to seg:0 */
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
*(ush*)&buf = 0;
table[next_ptr++].new_ptr = buf;
return buf;
}
void zcfree (voidpf opaque, voidpf ptr)
{
int n;
if (*(ush*)&ptr != 0) { /* object < 64K */
farfree(ptr);
return;
}
/* Find the original pointer */
for (n = 0; n < next_ptr; n++) {
if (ptr != table[n].new_ptr) continue;
farfree(table[n].org_ptr);
while (++n < next_ptr) {
table[n-1] = table[n];
}
next_ptr--;
return;
}
ptr = opaque; /* just to make some compilers happy */
Assert(0, "zcfree: ptr not found");
}
#endif /* __TURBOC__ */
#ifdef M_I86
/* Microsoft C in 16-bit mode */
# define MY_ZCALLOC
#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
# define _halloc halloc
# define _hfree hfree
#endif
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
if (opaque) opaque = 0; /* to make compiler happy */
return _halloc((long)items, size);
}
void zcfree (voidpf opaque, voidpf ptr)
{
if (opaque) opaque = 0; /* to make compiler happy */
_hfree(ptr);
}
#endif /* M_I86 */
#endif /* SYS16BIT */
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
#ifndef STDC
extern voidp malloc OF((uInt size));
extern voidp calloc OF((uInt items, uInt size));
extern void free OF((voidpf ptr));
#endif
voidpf zcalloc (opaque, items, size)
voidpf opaque;
unsigned items;
unsigned size;
{
if (opaque) items += size - size; /* make compiler happy */
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
(voidpf)calloc(items, size);
}
void zcfree (opaque, ptr)
voidpf opaque;
voidpf ptr;
{
free(ptr);
if (opaque) return; /* make compiler happy */
}
#endif /* MY_ZCALLOC */

View File

@ -0,0 +1,269 @@
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef ZUTIL_H
#define ZUTIL_H
#define ZLIB_INTERNAL
#include "zlib.h"
#ifdef STDC
# ifndef _WIN32_WCE
# include <stddef.h>
# endif
# include <string.h>
# include <stdlib.h>
#endif
#ifdef NO_ERRNO_H
# ifdef _WIN32_WCE
/* The Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used. We rename it to
* avoid conflict with other libraries that use the same workaround.
*/
# define errno z_errno
# endif
extern int errno;
#else
# ifndef _WIN32_WCE
# include <errno.h>
# endif
#endif
#ifndef local
# define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */
typedef unsigned char uch;
typedef uch FAR uchf;
typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = (char*)ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */
/* common constants */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default memLevel */
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
/* The three kinds of block type */
#define MIN_MATCH 3
#define MAX_MATCH 258
/* The minimum and maximum match lengths */
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
/* target dependencies */
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
# define OS_CODE 0x00
# if defined(__TURBOC__) || defined(__BORLANDC__)
# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes );
# else
# include <alloc.h>
# endif
# else /* MSC or DJGPP */
# include <malloc.h>
# endif
#endif
#ifdef AMIGA
# define OS_CODE 0x01
#endif
#if defined(VAXC) || defined(VMS)
# define OS_CODE 0x02
# define F_OPEN(name, mode) \
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
#endif
#if defined(ATARI) || defined(atarist)
# define OS_CODE 0x05
#endif
#ifdef OS2
# define OS_CODE 0x06
# ifdef M_I86
#include <malloc.h>
# endif
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
# define OS_CODE 0x07
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include <unix.h> /* for fdopen */
# else
# ifndef fdopen
# define fdopen(fd,mode) NULL /* No fdopen() */
# endif
# endif
#endif
#ifdef TOPS20
# define OS_CODE 0x0a
#endif
#ifdef WIN32
# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
# define OS_CODE 0x0b
# endif
#endif
#ifdef __50SERIES /* Prime/PRIMOS */
# define OS_CODE 0x0f
#endif
#if defined(_BEOS_) || defined(RISCOS)
# define fdopen(fd,mode) NULL /* No fdopen() */
#endif
#if (defined(_MSC_VER) && (_MSC_VER > 600))
# if defined(_WIN32_WCE)
# define fdopen(fd,mode) NULL /* No fdopen() */
# ifndef _PTRDIFF_T_DEFINED
typedef int ptrdiff_t;
# define _PTRDIFF_T_DEFINED
# endif
# else
# define fdopen(fd,type) _fdopen(fd,type)
# endif
#endif
/* common defaults */
#ifndef OS_CODE
# define OS_CODE 0x03 /* assume Unix */
#endif
#ifndef F_OPEN
# define F_OPEN(name, mode) fopen((name), (mode))
#endif
/* functions */
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#if defined(__CYGWIN__)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#ifndef HAVE_VSNPRINTF
# ifdef MSDOS
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
but for now we just assume it doesn't. */
# define NO_vsnprintf
# endif
# ifdef __TURBOC__
# define NO_vsnprintf
# endif
# ifdef WIN32
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
# define vsnprintf _vsnprintf
# endif
# endif
# ifdef __SASC
# define NO_vsnprintf
# endif
#endif
#ifdef VMS
# define NO_vsnprintf
#endif
#if defined(pyr)
# define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
/* Use our own functions for small and medium model with MSC <= 5.0.
* You may have to use the same strategy for Borland C (untested).
* The __SC__ check is for Symantec.
*/
# define NO_MEMCPY
#endif
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
# define HAVE_MEMCPY
#endif
#ifdef HAVE_MEMCPY
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
# define zmemcpy _fmemcpy
# define zmemcmp _fmemcmp
# define zmemzero(dest, len) _fmemset(dest, 0, len)
# else
# define zmemcpy memcpy
# define zmemcmp memcmp
# define zmemzero(dest, len) memset(dest, 0, len)
# endif
#else
extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
extern void zmemzero OF((Bytef* dest, uInt len));
#endif
/* Diagnostic functions */
#ifdef DEBUG
# include <stdio.h>
extern int z_verbose;
extern void z_error OF((char *m));
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
void zcfree OF((voidpf opaque, voidpf ptr));
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
#endif /* ZUTIL_H */

View File

@ -0,0 +1,18 @@
#define XSF_FALSE (0)
#define XSF_TRUE (!XSF_FALSE)
#ifdef __cplusplus
extern "C" {
#endif
int xsf_start(void *pfile, unsigned bytes);
int xsf_gen(void *pbuffer, unsigned samples);
int xsf_get_lib(char *pfilename, void **ppbuffer, unsigned *plength);
void xsf_term(void);
void xsf_set_extend_param(unsigned dwId, const wchar_t *lpPtr);
extern unsigned long dwChannelMute;
extern unsigned long dwChannelMute;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,719 @@
#include "leakchk.h"
#include "foobar2000/SDK/foobar2000.h"
#include "../pversion.h"
#include "../loadpe/loadpe.h"
#include "xsfdrv.h"
#include "tagget.h"
#include "xsfcfg.h"
enum
{
xsf_bits_per_sample = 16,
xsf_channels = 2,
#ifndef XSFDRIVER_SAMPLERATE
xsf_sample_rate = 44100,
#else
xsf_sample_rate = XSFDRIVER_SAMPLERATE,
#endif
xsf_bytes_per_sample = xsf_bits_per_sample / 8,
xsf_total_sample_width = xsf_bytes_per_sample * xsf_channels,
};
#define DEFAULT_BUFFER_SIZE (1024)
#define CHECK_SILENCE_BIAS 0x8000000
#ifndef CHECK_SILENCE_LEVEL
#define CHECK_SILENCE_LEVEL 7
#endif
typedef signed short xsfsample_t;
static HMODULE hDLL;
class xsf_drv
{
protected:
void *lpDrv;
IXSFDRV *lpif;
pfc::string8 m_libpath;
bool m_genok;
unsigned detectedSilenceSec;
unsigned detectedSilenceSample;
unsigned skipSilenceOnStartSec;
unsigned long prevSampleL;
unsigned long prevSampleR;
public:
bool isUTF8;
xsf_drv()
{
m_genok = false;
isUTF8 = false;
lpDrv = 0;
lpif = 0;
}
~xsf_drv()
{
freeDrv();
}
void setlibpath(pfc::string8 &p_libpath)
{
m_libpath.set_string(p_libpath.get_ptr());
}
void start(void *p, DWORD l)
{
if (loadDrv())
m_genok = !lpif->Start(p, l);
skipSilenceOnStartSec = CFGGetSkipSilenceOnStartSec();
detectedSilenceSec = 0;
detectedSilenceSample = 0;
prevSampleL = CHECK_SILENCE_BIAS;
prevSampleR = CHECK_SILENCE_BIAS;
}
unsigned long get_detect_silence()
{
return detectedSilenceSec;
}
int gen(void *pbuf, unsigned bufsize)
{
if (!lpif) return 0;
if (!m_genok) return 0;
xsfsample_t *ptop = static_cast<xsfsample_t *>(pbuf);
unsigned detectSilence = CFGGetDetectSilenceSec();
unsigned pos = 0;
if (lpif->dwInterfaceVersion >= 2)
{
bool output = false;
for (int i = 0; i < 4; i++)
{
unsigned long mute = CFGGetChannelMute(i);
output |= (mute != ~unsigned long(0));
lpif->SetChannelMute(i, mute);
}
if (!output) detectSilence = 0;
}
while (pos < bufsize)
{
unsigned ofs;
xsfsample_t *pblk = ptop + (pos << 1);
unsigned remain = bufsize - pos;
lpif->Gen(pblk, remain);
if (detectSilence || skipSilenceOnStartSec)
{
xsfsample_t *pskp = 0;
xsfsample_t *pcur = pblk;
for (ofs = 0; ofs < remain; ofs++)
{
long smpl = pcur[0];
long smpr = pcur[1];
bool silence = (((unsigned long)(smpl + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleL <= (CHECK_SILENCE_LEVEL) * 2) && (((unsigned long)(smpr + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleR <= (CHECK_SILENCE_LEVEL) * 2);
if (silence)
{
if (++detectedSilenceSample >= xsf_sample_rate)
{
detectedSilenceSample -= xsf_sample_rate;
detectedSilenceSec++;
if (skipSilenceOnStartSec && detectedSilenceSec >= skipSilenceOnStartSec)
{
skipSilenceOnStartSec = 0;
detectedSilenceSec = 0;
if (pblk != pcur) pskp = pcur;
}
}
}
else
{
detectedSilenceSample = 0;
detectedSilenceSec = 0;
if (skipSilenceOnStartSec)
{
skipSilenceOnStartSec = 0;
if (pblk != pcur) pskp = pcur;
}
}
prevSampleL = smpl + CHECK_SILENCE_BIAS;
prevSampleR = smpr + CHECK_SILENCE_BIAS;
pcur += 2;
}
if (skipSilenceOnStartSec)
{
}
else if (pskp)
{
while (pskp < pcur)
{
*(pblk++)= *(pskp++);
*(pblk++)= *(pskp++);
pos++;
}
}
else
{
pos += remain;
}
}
else
{
pos += remain;
}
}
return bufsize;
}
void stop()
{
if (!lpif) return;
lpif->Term();
m_genok = false;
}
protected:
bool aogetlib(pfc::string8 &filename, void **ppBuffer, DWORD *pdwSize)
{
try
{
if (!lpif) return false;
service_ptr_t<file> xsflib;
abort_callback_impl abort_cb;
xsfc::TStringM path(true, xsfc::TWin32::CanonicalizePath(xsfc::TString(true, m_libpath.get_ptr()) + xsfc::TString(true, filename.get_ptr())));
pfc::string8 xsfpath(path.GetM());
filesystem::g_open_read(xsflib, xsfpath, abort_cb);
DWORD dwfilesize = DWORD(xsflib->get_size_ex(abort_cb));
void *ret = lpif->LibAlloc(dwfilesize);
if (!ret) return false;
xsflib->read(ret, dwfilesize, abort_cb);
*ppBuffer = ret;
*pdwSize = dwfilesize;
return true;
} catch (xsfc::EShortOfMemory e) {
} catch (exception_io e) {
}
return false;
}
static int PASCAL XSFGETLIBCALLBACK(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize)
{
xsf_drv *pthis = static_cast<xsf_drv *>(lpWork);
pfc::string8 filename;
if (pthis->isUTF8)
{
filename.set_string(static_cast<const char *>(lpszFilename));
}
else
{
pfc::stringcvt::string_utf8_from_ansi valuea(static_cast<const char *>(lpszFilename));
filename.set_string(valuea.get_ptr());
}
return pthis->aogetlib(filename, ppBuffer, pdwSize) ? 0 : 1;
}
bool loadDrv(void)
{
if (lpif) return true;
pfc::string8 dllpath;
uGetModuleFileName(hDLL, dllpath);
pfc::string8 binpath(dllpath, pfc::scan_filename(dllpath));
binpath.add_string(XSFDRIVER_MODULENAME);
if (xsfc::TWin32::IsUnicodeSupportedOS())
{
pfc::stringcvt::string_wide_from_utf8 dllpathw(binpath);
lpDrv = XLoadLibraryW(dllpathw.get_ptr());
}
else
{
pfc::stringcvt::string_ansi_from_utf8 dllpatha(binpath);
lpDrv = XLoadLibraryA(dllpatha.get_ptr());
}
if (!lpDrv) return false;
LPFNXSFDRVSETUP xsfsetup = (LPFNXSFDRVSETUP)XGetProcAddress(lpDrv, XSFDRIVER_ENTRYNAME);
if (!xsfsetup)
{
XFreeLibrary(lpDrv);
lpDrv = 0;
return false;
}
lpif = xsfsetup(XSFGETLIBCALLBACK, this);
return true;
}
void freeDrv(void)
{
if (lpif)
{
lpif->Term();
lpif = 0;
}
if (lpDrv)
{
XFreeLibrary(lpDrv);
lpDrv = 0;
}
}
};
class input_xsf
{
protected:
xsf_drv drv;
pfc::array_t<t_uint8> m_filebuffer;
foobar2000_io::t_filesize m_filesize;
t_uint64 cur_smp;
t_uint64 len_smp;
t_uint64 fad_smp;
t_uint64 end_smp;
service_ptr_t<file> m_file;
pfc::array_t<t_uint8> m_buffer;
double m_volume;
bool m_hasvolume;
bool m_haslength;
bool m_write_UTF8;
unsigned m_flags;
typedef struct
{
class input_xsf *pThis;
file_info * p_info;
bool isUTF8;
} tagloadcbwork;
void tagloadsub(file_info & p_info, pfc::string8 &name, pfc::string8 &value)
{
if (!stricmp_utf8(name.get_ptr(), "game"))
p_info.meta_add("album", value.get_ptr());
else if (!stricmp_utf8(name.get_ptr(), "year"))
p_info.meta_add("date", value.get_ptr());
else if (!_strnicmp(name.get_ptr(), "_lib", 4) || !stricmp_utf8(name.get_ptr(), "fade") || !stricmp_utf8(name.get_ptr(), "length") || !stricmp_utf8(name.get_ptr(), "volume"))
p_info.info_set(name.get_ptr(), value.get_ptr());
else if (!stricmp_utf8(name.get_ptr(), "replaygain_track_gain"))
{
replaygain_info rg = p_info.get_replaygain();
rg.set_track_gain_text(value.get_ptr());
p_info.set_replaygain(rg);
}
else if (!stricmp_utf8(name.get_ptr(), "replaygain_track_peak"))
{
replaygain_info rg = p_info.get_replaygain();
rg.set_track_peak_text(value.get_ptr());
p_info.set_replaygain(rg);
}
else if (!stricmp_utf8(name.get_ptr(), "replaygain_album_gain"))
{
replaygain_info rg = p_info.get_replaygain();
rg.set_album_gain_text(value.get_ptr());
p_info.set_replaygain(rg);
}
else if (!stricmp_utf8(name.get_ptr(), "replaygain_album_peak"))
{
replaygain_info rg = p_info.get_replaygain();
rg.set_album_peak_text(value.get_ptr());
p_info.set_replaygain(rg);
}
else
p_info.meta_add(name.get_ptr(), value.get_ptr());
}
static enum XSFTag::enum_callback_returnvalue tagloadcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd)
{
if (pNameTop == pNameEnd) return XSFTag::enum_continue;
tagloadcbwork *pcbwork = static_cast<tagloadcbwork *>(pWork);
pfc::string8 name;
name.set_string(pNameTop, pNameEnd - pNameTop);
pfc::string8 value;
if (pcbwork->isUTF8)
{
value.set_string(pValueTop, pValueEnd - pValueTop);
}
else
{
pfc::stringcvt::string_utf8_from_ansi valuea(pValueTop, pValueEnd - pValueTop);
value.set_string(valuea.get_ptr());
}
pcbwork->pThis->tagloadsub(*pcbwork->p_info, name, value);
return XSFTag::enum_continue;
}
void tagload(file_info & p_info)
{
BYTE *pData = m_filebuffer.get_ptr();
DWORD dwSize = DWORD(m_filesize);
bool isUTF8 = XSFTag::Exists("utf8", pData, dwSize);
drv.isUTF8 = isUTF8;
tagloadcbwork cbwork;
cbwork.isUTF8 = isUTF8;
cbwork.pThis = this;
cbwork.p_info= &p_info;
XSFTag::Enum(tagloadcb, &cbwork, pData, dwSize);
return;
}
void tagsave(const file_info & p_info, abort_callback & p_abort)
{
BYTE *pData = m_filebuffer.get_ptr();
DWORD dwSize = DWORD(m_filesize);
DWORD dwPos = XSFTag::SearchRaw(pData, dwSize);
if (!dwPos || dwPos >= dwSize) return;
m_file->truncate(dwPos, p_abort);
m_file->seek(dwPos, p_abort);
m_write_UTF8 = p_info.meta_exists("utf8");
tag_write("[TAG]", p_abort);
if (m_write_UTF8)
tag_writel("utf8=1\x0a", p_abort);
/* write play info */
t_size icnt = p_info.info_get_count();
for (t_size i = 0; i < icnt; i++)
{
const char *name = p_info.info_enum_name(i);
if (!_strnicmp(name, "_lib", 4) || !stricmp_utf8(name, "fade") || !stricmp_utf8(name, "length") || !stricmp_utf8(name, "volume"))
{
const char *value = p_info.info_enum_value(i);
if (*value)
{
tag_writel(name, p_abort);
tag_writel("=", p_abort);
tag_write(value, p_abort);
tag_writel("\x0a", p_abort);
}
}
}
/* write meta data */
t_size mcnt = p_info.meta_get_count();
for (t_size m = 0; m < mcnt; m++)
{
const char *name = p_info.meta_enum_name(m);
if (!stricmp_utf8(name, "utf8"))
continue;
else if (!stricmp_utf8(name, "album"))
name = "game";
else if (!stricmp_utf8(name, "date"))
name = "year";
t_size ncnt = p_info.meta_enum_value_count(m);
for (t_size n = 0; n < ncnt; n++)
{
const char *value = p_info.meta_enum_value(m, n);
if (*value)
{
tag_writel(name, p_abort);
tag_writel("=", p_abort);
tag_write(value, p_abort);
tag_writel("\x0a", p_abort);
}
}
}
/* write replay gain */
pfc::array_t<char> rgbuf;
replaygain_info rg = p_info.get_replaygain();
rgbuf.set_size(rg.text_buffer_size);
if (rg.m_album_gain > rg.gain_invalid)
{
rg.format_album_gain(rgbuf.get_ptr());
tag_writel("replaygain_album_gain", p_abort);
tag_writel("=", p_abort);
tag_write(rgbuf.get_ptr(), p_abort);
tag_writel("\x0a", p_abort);
}
if (rg.m_album_peak > rg.peak_invalid)
{
rg.format_album_peak(rgbuf.get_ptr());
tag_writel("replaygain_album_peak", p_abort);
tag_writel("=", p_abort);
tag_write(rgbuf.get_ptr(), p_abort);
tag_writel("\x0a", p_abort);
}
if (rg.m_track_gain > rg.gain_invalid)
{
rg.format_track_gain(rgbuf.get_ptr());
tag_writel("replaygain_track_gain", p_abort);
tag_writel("=", p_abort);
tag_write(rgbuf.get_ptr(), p_abort);
tag_writel("\x0a", p_abort);
}
if (rg.m_track_peak > rg.peak_invalid)
{
rg.format_track_peak(rgbuf.get_ptr());
tag_writel("replaygain_track_peak", p_abort);
tag_writel("=", p_abort);
tag_write(rgbuf.get_ptr(), p_abort);
tag_writel("\x0a", p_abort);
}
m_file->set_eof(p_abort);
}
void tag_writel(const char *p, abort_callback & p_abort)
{
t_size l = strlen(p);
pfc::array_t<char> lbuf;
lbuf.set_size(l);
char *d = lbuf.get_ptr();
for (t_size i = 0; i < l; i++)
d[i] = pfc::ascii_tolower(p[i]);
m_file->write(d, l, p_abort);
}
void tag_writeA(const char *p, t_size l, abort_callback & p_abort)
{
pfc::stringcvt::string_ansi_from_utf8 valuea(p, l);
m_file->write(valuea.get_ptr(), valuea.length(), p_abort);
}
void tag_write(const char *p, abort_callback & p_abort)
{
t_size l = strlen(p);
pfc::array_t<char> lbuf;
lbuf.set_size(l);
char *d = lbuf.get_ptr();
for (t_size i = 0; i < l; i++)
{
if (p[i] == 0x0a)
d[i] = ';';
else if (p[i] > 0x00 && p[i] < 0x20)
d[i] = ' ';
else
d[i] = p[i];
}
if (m_write_UTF8)
m_file->write(d, l, p_abort);
else
tag_writeA(d, l, p_abort);
}
void xsf_restart()
{
drv.start(m_filebuffer.get_ptr(), DWORD(m_filebuffer.get_size()));
cur_smp = 0;
}
void xsf_reopen(service_ptr_t<file> & p_file, abort_callback & p_abort)
{
m_filesize = p_file->get_size_ex(p_abort);
m_filebuffer.set_size(t_size(m_filesize));
p_file->read(m_filebuffer.get_ptr(), t_size(m_filesize), p_abort);
xsf_reload();
}
void xsf_reload(void)
{
xsfc::TString tagvolume = XSFTag::Get("volume", m_filebuffer.get_ptr(), size_t(m_filesize));
t_uint32 length = XSFTag::GetLengthMS(m_filebuffer.get_ptr(), size_t(m_filesize), CFGGetDefaultLength());
t_uint32 fade = XSFTag::GetFadeMS(m_filebuffer.get_ptr(), size_t(m_filesize), CFGGetDefaultFade());
m_haslength = XSFTag::Exists("length", m_filebuffer.get_ptr(), size_t(m_filesize));
m_volume = 1.0;
m_hasvolume = false;
if (tagvolume[0])
{
m_volume = tagvolume.GetFloat();
m_hasvolume = (m_volume != 1.0);
}
len_smp = t_uint64(length) * xsf_sample_rate / 1000;
fad_smp = t_uint64(fade) * xsf_sample_rate / 1000;
end_smp = len_smp + fad_smp;
}
void xsf_seek(t_uint64 &seek_smp, abort_callback & p_abort)
{
t_size bufsize = m_buffer.get_size() / xsf_total_sample_width;
if (bufsize < xsf_total_sample_width)
{
bufsize = DEFAULT_BUFFER_SIZE;
m_buffer.set_size(bufsize * xsf_total_sample_width);
}
if (seek_smp < cur_smp)
{
xsf_restart();
}
while (seek_smp - cur_smp > bufsize)
{
if (p_abort.is_aborting())
return;
drv.gen(m_buffer.get_ptr(), DWORD(bufsize));
cur_smp += bufsize;
}
if (seek_smp - cur_smp > 0)
{
drv.gen(m_buffer.get_ptr(), DWORD(seek_smp - cur_smp));
cur_smp = seek_smp;
}
}
public:
void open(service_ptr_t<file> p_filehint,const char * p_path,t_input_open_reason p_reason,abort_callback & p_abort)
{
m_file = p_filehint;//p_filehint may be null, hence next line
input_open_file_helper(m_file,p_path,p_reason,p_abort);//if m_file is null, opens file with appropriate privileges for our operation (read/write for writing tags, read-only otherwise).
pfc::string8 libpath(p_path, pfc::scan_filename(p_path));
drv.setlibpath(libpath);
xsf_reopen(m_file, p_abort);
if (p_reason == input_open_decode)
xsf_restart();
}
void get_info(file_info & p_info,abort_callback & p_abort)
{
(void)p_abort;
p_info.set_length(audio_math::samples_to_time( end_smp, xsf_sample_rate));
p_info.info_set_int("samplerate",xsf_sample_rate);
p_info.info_set_int("channels",xsf_channels);
p_info.info_set_int("bitspersample",xsf_bits_per_sample);
p_info.info_set("encoding",FOOBAR2000COMPONENT_ENCODING);
p_info.info_set_bitrate((xsf_bits_per_sample * xsf_channels * xsf_sample_rate + 500 /* rounding for bps to kbps*/ ) / 1000 /* bps to kbps */);
tagload(p_info);
}
t_filestats get_file_stats(abort_callback & p_abort) {return m_file->get_stats(p_abort);}
void decode_initialize(unsigned p_flags,abort_callback & p_abort)
{
(void)p_abort;
m_flags = p_flags;
}
bool decode_run(audio_chunk & p_chunk,abort_callback & p_abort)
{
(void)p_abort;
bool fPlayInfinitely = CFGGetPlayInfinitely() && !(m_flags & input_flag_no_looping) && (m_flags & input_flag_playback);
if ((cur_smp >= end_smp && !fPlayInfinitely) || (!m_haslength && CFGGetDetectSilenceSec() && CFGGetDetectSilenceSec() <= drv.get_detect_silence()))
{
return false;
}
m_buffer.set_size(DEFAULT_BUFFER_SIZE * xsf_total_sample_width);
t_size bufsize = m_buffer.get_size() / xsf_total_sample_width;
drv.gen(m_buffer.get_ptr(), DWORD(bufsize));
if (!fPlayInfinitely && cur_smp + bufsize > end_smp)
bufsize = t_size(end_smp - cur_smp);
cur_smp += bufsize;
p_chunk.set_data_fixedpoint(m_buffer.get_ptr(),bufsize * xsf_total_sample_width,xsf_sample_rate,xsf_channels,xsf_bits_per_sample,audio_chunk::g_guess_channel_config(xsf_channels));
double cfgvolume = 1;
bool hascfgvolume = (m_flags & input_flag_playback) && CFGGetVolume(cfgvolume);
if (hascfgvolume || m_hasvolume || (!fPlayInfinitely && (fad_smp && cur_smp + bufsize >= len_smp)))
{
audio_sample *psmp = p_chunk.get_data();
t_uint64 i;
double volume = m_volume * cfgvolume;
for (i = cur_smp; i < cur_smp + bufsize; i++)
{
if (fPlayInfinitely || i < len_smp)
{
psmp[0] = float(psmp[0] * volume);
psmp[1] = float(psmp[1] * volume);
}
else if (i < end_smp)
{
double scale = volume * double(len_smp + fad_smp - i) / double(fad_smp);
psmp[0] = float(psmp[0] * scale);
psmp[1] = float(psmp[1] * scale);
}
else
{
psmp[0] = 0;
psmp[1] = 0;
}
psmp += 2;
}
}
return true;
}
void decode_seek(double p_seconds,abort_callback & p_abort)
{
if (!decode_can_seek())
{
throw exception_io_object_not_seekable();
}
else
{
t_uint64 seek_pos(t_uint64(p_seconds * xsf_sample_rate));
xsf_seek(seek_pos, p_abort);
}
}
bool decode_can_seek() {return true;}
bool decode_get_dynamic_info(file_info & p_out, double & p_timestamp_delta) { (void)p_out, p_timestamp_delta; return false; }
bool decode_get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta) { (void)p_out, p_timestamp_delta; return false; }
void decode_on_idle(abort_callback & p_abort) { m_file->on_idle(p_abort); }
void retag(const file_info & p_info,abort_callback & p_abort)
{
tagsave(p_info, p_abort);
m_file->reopen(p_abort);
xsf_reopen(m_file, p_abort);
}
static bool g_is_our_content_type(const char * p_content_type) { (void)p_content_type; return false;}
static bool g_is_our_path(const char * p_path,const char * p_extension) { (void)p_path, p_extension; return FOOBAR2000COMPONENT_EXT_CHECK; }
};
static input_singletrack_factory_t<input_xsf> g_input_xsf_factory;
DECLARE_COMPONENT_VERSION(FOOBAR2000COMPONENT_NAME,FOOBAR2000COMPONENT_VERSION,FOOBAR2000COMPONENT_ABOUT);
DECLARE_FILE_TYPE(FOOBAR2000COMPONENT_TYPE,FOOBAR2000COMPONENT_EXTS);
extern "C" void fb2k_config_init(HINSTANCE hinstDLL);
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
#if defined(_MSC_VER) && defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
hDLL = hModule;
fb2k_config_init(hDLL);
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{
}
return TRUE;
}

View File

@ -0,0 +1,709 @@
#include "foobar2000/SDK/foobar2000.h"
#include "../pversion.h"
#include "../loadpe/loadpe.h"
#include "xsfdrv.h"
#include "tagget.h"
#include "xsfcfg.h"
enum
{
xsf_bits_per_sample = 16,
xsf_channels = 2,
#ifndef XSFDRIVER_SAMPLERATE
xsf_sample_rate = 44100,
#else
xsf_sample_rate = XSFDRIVER_SAMPLERATE,
#endif
xsf_bytes_per_sample = xsf_bits_per_sample / 8,
xsf_total_sample_width = xsf_bytes_per_sample * xsf_channels
};
#define DEFAULT_BUFFER_SIZE (1024)
#define CHECK_SILENCE_BIAS 0x8000000
#ifndef CHECK_SILENCE_LEVEL
#define CHECK_SILENCE_LEVEL 7
#endif
typedef signed short xsfsample_t;
static HMODULE hDLL;
class ReaderHolder
{
void Free()
{
if (ptr)
{
ptr->reader_release();
ptr = 0;
}
}
public:
reader *ptr;
ReaderHolder(reader *p = 0)
: ptr(p)
{
}
~ReaderHolder()
{
Free();
}
reader *GetReader()
{
return ptr;
}
void SetReader(reader * p)
{
Free();
ptr = p;
}
bool Open(const xsfc::TString &fn)
{
SetReader(file::g_open(xsfc::TStringM(true, fn), reader::MODE_READ));
return ptr != 0;
}
};
class xsf_drv
{
protected:
void *lpDrv;
IXSFDRV *lpif;
xsfc::TString m_libpath;
bool m_genok;
unsigned detectedSilenceSec;
unsigned detectedSilenceSample;
unsigned skipSilenceOnStartSec;
unsigned long prevSampleL;
unsigned long prevSampleR;
public:
bool isUTF8;
xsf_drv()
{
m_genok = false;
isUTF8 = false;
lpDrv = 0;
lpif = 0;
}
~xsf_drv()
{
freeDrv();
}
void setlibpath(const xsfc::TString &p_libpath)
{
m_libpath = p_libpath;
}
void start(void *p, DWORD l)
{
if (loadDrv())
{
if (lpif->dwInterfaceVersion >= 3)
{
lpif->SetExtendParam(1, CFGGetExtendParam1());
lpif->SetExtendParam(2, CFGGetExtendParam2());
}
m_genok = !lpif->Start(p, l);
}
skipSilenceOnStartSec = CFGGetSkipSilenceOnStartSec();
detectedSilenceSec = 0;
detectedSilenceSample = 0;
prevSampleL = CHECK_SILENCE_BIAS;
prevSampleR = CHECK_SILENCE_BIAS;
}
unsigned long get_detect_silence()
{
return detectedSilenceSec;
}
int gen(void *pbuf, unsigned bufsize)
{
if (!lpif) return 0;
if (!m_genok) return 0;
xsfsample_t *ptop = static_cast<xsfsample_t *>(pbuf);
unsigned detectSilence = CFGGetDetectSilenceSec();
unsigned pos = 0;
if (lpif->dwInterfaceVersion >= 2)
{
bool output = false;
for (int i = 0; i < 4; i++)
{
unsigned long mute = CFGGetChannelMute(i);
output |= (mute != ~unsigned long(0));
lpif->SetChannelMute(i, mute);
}
if (!output) detectSilence = 0;
}
while (pos < bufsize)
{
unsigned ofs;
xsfsample_t *pblk = ptop + (pos << 1);
unsigned remain = bufsize - pos;
lpif->Gen(pblk, remain);
if (detectSilence || skipSilenceOnStartSec)
{
xsfsample_t *pskp = 0;
xsfsample_t *pcur = pblk;
for (ofs = 0; ofs < remain; ofs++)
{
long smpl = pcur[0];
long smpr = pcur[1];
bool silence = (((unsigned long)(smpl + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleL <= (CHECK_SILENCE_LEVEL) * 2) && (((unsigned long)(smpr + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleR <= (CHECK_SILENCE_LEVEL) * 2);
if (silence)
{
if (++detectedSilenceSample >= xsf_sample_rate)
{
detectedSilenceSample -= xsf_sample_rate;
detectedSilenceSec++;
if (skipSilenceOnStartSec && detectedSilenceSec >= skipSilenceOnStartSec)
{
skipSilenceOnStartSec = 0;
detectedSilenceSec = 0;
if (pblk != pcur) pskp = pcur;
}
}
}
else
{
detectedSilenceSample = 0;
detectedSilenceSec = 0;
if (skipSilenceOnStartSec)
{
skipSilenceOnStartSec = 0;
if (pblk != pcur) pskp = pcur;
}
}
prevSampleL = smpl + CHECK_SILENCE_BIAS;
prevSampleR = smpr + CHECK_SILENCE_BIAS;
pcur += 2;
}
if (skipSilenceOnStartSec)
{
}
else if (pskp)
{
while (pskp < pcur)
{
*(pblk++)= *(pskp++);
*(pblk++)= *(pskp++);
pos++;
}
}
else
{
pos += remain;
}
}
else
{
pos += remain;
}
}
return bufsize;
}
void stop()
{
if (!lpif) return;
lpif->Term();
m_genok = false;
}
protected:
bool aogetlib(xsfc::TString filename, void **ppBuffer, DWORD *pdwSize)
{
if (!lpif) return false;
ReaderHolder xsflib;
xsfc::TString path = xsfc::TWin32::CanonicalizePath(m_libpath + filename);
if (!xsflib.Open(path)) return false;
__int64 filesize64 = xsflib.GetReader()->get_length();
DWORD dwfilesize = DWORD(filesize64);
if (filesize64 == -1 || filesize64 != dwfilesize) return false;
void *ret = lpif->LibAlloc(dwfilesize);
if (!ret) return false;
xsflib.GetReader()->read(ret, dwfilesize);
*ppBuffer = ret;
*pdwSize = dwfilesize;
return true;
}
static int PASCAL XSFGETLIBCALLBACK(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize)
{
xsf_drv *pthis = static_cast<xsf_drv *>(lpWork);
xsfc::TString filename;
if (pthis->isUTF8)
{
filename = xsfc::TString(true, lpszFilename);
}
else
{
filename = xsfc::TString(false, lpszFilename);
}
return pthis->aogetlib(filename, ppBuffer, pdwSize) ? 0 : 1;
}
bool loadDrv(void)
{
if (lpif) return true;
xsfc::TString binpath = xsfc::TWin32::ExtractPath(xsfc::TWin32::ModulePath(hDLL)) + XSFDRIVER_MODULENAME;
if (xsfc::TWin32::IsUnicodeSupportedOS())
{
lpDrv = XLoadLibraryW(binpath);
}
else
{
lpDrv = XLoadLibraryA(xsfc::TStringM(binpath));
}
if (!lpDrv) return false;
LPFNXSFDRVSETUP xsfsetup = (LPFNXSFDRVSETUP)XGetProcAddress(lpDrv, XSFDRIVER_ENTRYNAME);
if (!xsfsetup)
{
XFreeLibrary(lpDrv);
lpDrv = 0;
return false;
}
lpif = xsfsetup(XSFGETLIBCALLBACK, this);
return true;
}
void freeDrv(void)
{
if (lpif)
{
lpif->Term();
lpif = 0;
}
if (lpDrv)
{
XFreeLibrary(lpDrv);
lpDrv = 0;
}
}
};
class input_xsf : public input_pcm
{
protected:
typedef signed short audio_sample_t;
typedef __int64 t_size;
typedef unsigned __int64 t_uint64;
xsf_drv drv;
array_t<BYTE> m_filebuffer;
t_size m_filesize;
t_uint64 cur_smp;
t_uint64 len_smp;
t_uint64 fad_smp;
t_uint64 end_smp;
array_t<unsigned char> m_buffer;
double m_volume;
bool m_hasvolume;
bool m_haslength;
bool m_write_UTF8;
unsigned m_flags;
typedef struct
{
class input_xsf *pThis;
file_info * p_info;
bool isUTF8;
} tagloadcbwork;
void tagloadsub(file_info & p_info, const char *name, const xsfc::TStringM &value)
{
if (!stricmp_utf8(name, "game"))
p_info.meta_add("album", value);
else if (!stricmp_utf8(name, "year"))
p_info.meta_add("date", value);
else if (!_strnicmp(name, "_lib", 4) || !stricmp_utf8(name, "fade") || !stricmp_utf8(name, "length") || !stricmp_utf8(name, "volume"))
p_info.info_set(name, value);
else if (!stricmp_utf8(name, "replaygain_track_gain"))
{
p_info.info_set_replaygain_track_gain(pfc_string_to_float(value));
}
else if (!stricmp_utf8(name, "replaygain_track_peak"))
{
p_info.info_set_replaygain_track_peak(pfc_string_to_float(value));
}
else if (!stricmp_utf8(name, "replaygain_album_gain"))
{
p_info.info_set_replaygain_album_gain(pfc_string_to_float(value));
}
else if (!stricmp_utf8(name, "replaygain_album_peak"))
{
p_info.info_set_replaygain_album_peak(pfc_string_to_float(value));
}
else
p_info.meta_add(name, value);
}
static enum XSFTag::enum_callback_returnvalue tagloadcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd)
{
if (pNameTop == pNameEnd) return XSFTag::enum_continue;
tagloadcbwork *pcbwork = static_cast<tagloadcbwork *>(pWork);
xsfc::TString name;
xsfc::TString value;
if (pcbwork->isUTF8)
{
name = xsfc::TString(true, pNameTop, pNameEnd - pNameTop);
value = xsfc::TString(true, pValueTop, pValueEnd - pValueTop);
}
else
{
name = xsfc::TString(false, pNameTop, pNameEnd - pNameTop);
value = xsfc::TString(false, pValueTop, pValueEnd - pValueTop);
}
pcbwork->pThis->tagloadsub(*pcbwork->p_info, xsfc::TStringM(true, name), xsfc::TStringM(true, value));
return XSFTag::enum_continue;
}
void tagload(file_info & p_info)
{
BYTE *pData = &m_filebuffer[0];
DWORD dwSize = DWORD(m_filesize);
bool isUTF8 = XSFTag::Exists("utf8", pData, dwSize);
drv.isUTF8 = isUTF8;
tagloadcbwork cbwork;
cbwork.isUTF8 = isUTF8;
cbwork.pThis = this;
cbwork.p_info= &p_info;
XSFTag::Enum(tagloadcb, &cbwork, pData, dwSize);
return;
}
bool tag_writel(const char *p, reader *r)
{
string8 value;
value.convert_to_lower_ascii(p);
const char *pL = value.get_ptr();
t_size lL = strlen(p);
return r->write(pL, lL) == lL;
}
bool tag_writeA(const char *p, t_size l, reader *r)
{
xsfc::TString value(true, p, l);
xsfc::TStringM valueA(false, value);
const char *pA = valueA;
t_size lA = strlen(pA);
return r->write(pA, lA) == lA;
}
bool tag_writeU(const char *p, t_size l, reader *r)
{
return r->write(p, l) == l;
}
bool tag_write(const char *p, reader *r)
{
t_size l = strlen(p);
array_t<char> lbuf;
if (!lbuf.resize(l)) return false;
char *d = &lbuf[0];
for (t_size i = 0; i < l; i++)
{
if (p[i] == 0x0a)
d[i] = ';';
else if (p[i] > 0x00 && p[i] < 0x20)
d[i] = ' ';
else
d[i] = p[i];
}
return (m_write_UTF8) ? tag_writeU(d, l, r) : tag_writeA(d, l, r);
}
bool tagsave(reader *r, const file_info & p_info)
{
BYTE *pData = &m_filebuffer[0];
DWORD dwSize = DWORD(m_filesize);
DWORD dwPos = XSFTag::SearchRaw(pData, dwSize);
if (!dwPos || dwPos >= dwSize) return false;
if (!r->seek(dwPos)) return false;
m_write_UTF8 = p_info.meta_get_count_by_name("utf8") > 0;
tag_write("[TAG]", r);
if (m_write_UTF8)
tag_writel("utf8=1\x0a", r);
/* write play info */
t_size icnt = p_info.info_get_count();
for (t_size i = 0; i < icnt; i++)
{
const char *name = p_info.info_enum_name(i);
if (!_strnicmp(name, "_lib", 4) || !stricmp_utf8(name, "fade") || !stricmp_utf8(name, "length") || !stricmp_utf8(name, "volume") || !stricmp_utf8(name, "replaygain_album_gain") || !stricmp_utf8(name, "replaygain_album_peak") || !stricmp_utf8(name, "replaygain_track_gain") || !stricmp_utf8(name, "replaygain_track_peak"))
{
const char *value = p_info.info_enum_value(i);
if (*value)
{
tag_writel(name, r);
tag_writel("=", r);
tag_write(value, r);
tag_writel("\x0a", r);
}
}
}
/* write meta data */
t_size mcnt = p_info.meta_get_count();
for (t_size m = 0; m < mcnt; m++)
{
const char *name = p_info.meta_enum_name(m);
if (!stricmp_utf8(name, "utf8"))
continue;
else if (!stricmp_utf8(name, "album"))
name = "game";
else if (!stricmp_utf8(name, "date"))
name = "year";
const char *value = p_info.meta_enum_value(m);
if (*value)
{
tag_writel(name, r);
tag_writel("=", r);
tag_write(value, r);
tag_writel("\x0a", r);
}
}
r->set_eof();
return true;
}
void xsf_restart()
{
drv.start(&m_filebuffer[0], DWORD(m_filebuffer.size()));
cur_smp = 0;
}
bool xsf_reopen(reader *r)
{
m_filesize = r->get_length();
t_size l = t_size(m_filesize);
if (!m_filebuffer.resize(t_size(m_filesize))) return false;
return r->read(&m_filebuffer[0], l) == l;
}
void xsf_reload(void)
{
xsfc::TString tagvolume = XSFTag::Get("volume", &m_filebuffer[0], size_t(m_filesize)) ;
unsigned length = XSFTag::GetLengthMS(&m_filebuffer[0], size_t(m_filesize), CFGGetDefaultLength());
unsigned fade = XSFTag::GetFadeMS(&m_filebuffer[0], size_t(m_filesize), CFGGetDefaultFade());
m_haslength = XSFTag::Exists("length", &m_filebuffer[0], size_t(m_filesize));
m_volume = 1.0;
m_hasvolume = false;
if (tagvolume[0])
{
m_volume = tagvolume.GetFloat();
m_hasvolume = (m_volume != 1.0);
}
len_smp = t_uint64(length) * xsf_sample_rate / 1000;
fad_smp = t_uint64(fade) * xsf_sample_rate / 1000;
end_smp = len_smp + fad_smp;
}
void xsf_seek(t_uint64 &seek_smp)
{
t_size bufsize = m_buffer.size() / xsf_total_sample_width;
if (bufsize < xsf_total_sample_width)
{
bufsize = DEFAULT_BUFFER_SIZE;
m_buffer.resize(bufsize * xsf_total_sample_width);
}
if (seek_smp < cur_smp)
{
xsf_restart();
}
while (seek_smp - cur_smp > bufsize)
{
drv.gen(&m_buffer[0], DWORD(bufsize));
cur_smp += bufsize;
}
if (seek_smp - cur_smp > 0)
{
drv.gen(&m_buffer[0], DWORD(seek_smp - cur_smp));
cur_smp = seek_smp;
}
}
public:
void get_info(file_info & p_info)
{
p_info.set_length(::MulDiv(end_smp, 1, xsf_sample_rate));
p_info.info_set_int("samplerate",xsf_sample_rate);
p_info.info_set_int("channels",xsf_channels);
p_info.info_set_int("bitspersample",xsf_bits_per_sample);
p_info.info_set("encoding",FOOBAR2000COMPONENT_ENCODING);
p_info.info_set_bitrate((xsf_bits_per_sample * xsf_channels * xsf_sample_rate + 500 /* rounding for bps to kbps*/ ) / 1000 /* bps to kbps */);
tagload(p_info);
}
bool open(reader * r,file_info * info,unsigned flags)
{
m_flags = flags;
xsf_reopen(r);
xsf_reload();
if( flags & input::OPEN_FLAG_GET_INFO)
get_info(*info);
if (flags & input::OPEN_FLAG_DECODE)
{
const char *playpathutf8 = info->get_file_path();
xsfc::TString playpath(true, playpathutf8);
xsfc::TString libpath = xsfc::TWin32::ExtractPath(playpath);
drv.setlibpath(libpath);
xsf_restart();
}
return true;
}
inline audio_sample_t clip_mul(signed s1, double s2)
{
double r = s1 * s2;
if (r > 0x7fff)
r = 0x7fff;
else if (r < -0x8000)
r = -0x8000;
return audio_sample_t(r);
}
int get_samples_pcm(void ** out_buffer,int * out_size, int * srate, int * bps, int * nch)
{
bool fPlayInfinitely = CFGGetPlayInfinitely() && !(m_flags & OPEN_FLAG_NO_LOOPING);
if ((cur_smp >= end_smp && !fPlayInfinitely) || (!m_haslength && CFGGetDetectSilenceSec() && CFGGetDetectSilenceSec() <= drv.get_detect_silence()))
{
return false;
}
unsigned reqssize = DEFAULT_BUFFER_SIZE * xsf_total_sample_width;
if (m_buffer.size() < reqssize && !m_buffer.resize(reqssize))
return false;
t_size bufsize = m_buffer.size() / xsf_total_sample_width;
drv.gen(&m_buffer[0], DWORD(bufsize));
if (!fPlayInfinitely && cur_smp + bufsize > end_smp)
bufsize = t_size(end_smp - cur_smp);
*out_buffer = &m_buffer[0];
*out_size = bufsize * xsf_total_sample_width;
*srate = xsf_sample_rate;
*bps = xsf_bits_per_sample;
*nch = xsf_channels;
cur_smp += bufsize;
double cfgvolume = 1;
bool hascfgvolume = CFGGetVolume(cfgvolume);
if (hascfgvolume || m_hasvolume || (!fPlayInfinitely && (fad_smp && cur_smp + bufsize >= len_smp)))
{
audio_sample_t *psmp = (audio_sample_t *)&m_buffer[0];
t_uint64 i;
double volume = m_volume * cfgvolume;
for (i = cur_smp; i < cur_smp + bufsize; i++)
{
if (fPlayInfinitely || i < len_smp)
{
psmp[0] = clip_mul(psmp[0] , volume);
psmp[1] = clip_mul(psmp[1] , volume);
}
else if (i < end_smp)
{
double scale = volume * double(__int64(len_smp + fad_smp - i)) / double(__int64(fad_smp));
psmp[0] = clip_mul(psmp[0] , scale);
psmp[1] = clip_mul(psmp[1] , scale);
}
else
{
psmp[0] = 0;
psmp[1] = 0;
}
psmp += 2;
}
}
return true;
}
bool can_seek() {return true;}
bool seek(double p_seconds)
{
if (can_seek())
{
t_uint64 seek_pos(t_uint64(p_seconds * xsf_sample_rate));
xsf_seek(seek_pos);
return true;
}
return false;
}
bool is_our_content_type(const char * url,const char * type) { (void)url, type; return false;}
bool test_filename(const char * p_path,const char * p_extension) { (void)p_path, p_extension; return FOOBAR2000COMPONENT_EXT_CHECK; }
set_info_t set_info(reader *r, const file_info * info)
{
xsf_reopen(r);
return tagsave(r, *info) ? SET_INFO_SUCCESS : SET_INFO_FAILURE;
}
};
static input_factory<input_xsf> g_input_xsf_factory;
DECLARE_COMPONENT_VERSION(FOOBAR2000COMPONENT_NAME,FOOBAR2000COMPONENT_VERSION,FOOBAR2000COMPONENT_ABOUT);
DECLARE_FILE_TYPE(FOOBAR2000COMPONENT_TYPE,FOOBAR2000COMPONENT_EXTS);
extern "C" void fb2k_config_init(HINSTANCE hinstDLL);
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
hDLL = hModule;
fb2k_config_init(hDLL);
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{
}
return TRUE;
}

View File

@ -0,0 +1,269 @@
#include "leakchk.h"
#include "foobar2000/SDK/foobar2000.h"
#include "../pversion.h"
#include "tagget.h"
#include "xsfcfg.h"
namespace
{
HMODULE hDLL;
const GUID cfgguid1 = XSFDRIVER_GUID1;
const GUID cfgguid2 = XSFDRIVER_GUID2;
cfg_string cfg_fooxsf(cfgguid2, "");
class foo_config : public IConfigIO
{
protected:
typedef struct
{
xsfc::TString output;
xsfc::TString newvalue;
xsfc::TStringM newname;
size_t newnamelen;
bool exist;
}
cbw_t;
static enum XSFTag::enum_callback_returnvalue scv_cb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd)
{
cbw_t *pcbw = static_cast<cbw_t *>(pWork);
xsfc::TString name(true, pNameTop, pNameEnd - pNameTop);
if (pcbw->newnamelen == pNameEnd - pNameTop && !_strnicmp(pNameTop, pcbw->newname, pcbw->newnamelen))
{
pcbw->exist = true;
pcbw->output = pcbw->output + name + xsfc::TString(L"=") + pcbw->newvalue + xsfc::TString(L"\n");
}
else
{
xsfc::TString value(true, pValueTop, pValueEnd - pValueTop);
pcbw->output = pcbw->output + name + xsfc::TString(L"=") + value + xsfc::TString(L"\n");
}
return XSFTag::enum_continue;
}
void SetConfigValue(const wchar_t *name, xsfc::TString value)
{
const char *idata = cfg_fooxsf.get_ptr();
size_t isize = xsfc::StrNLen<char>(idata);
cbw_t cbw;
cbw.newvalue = value;
cbw.newname = xsfc::TStringM(true, name);
cbw.newnamelen = xsfc::StrNLen<char>(cbw.newname);
cbw.exist = false;
XSFTag::EnumRaw(scv_cb, &cbw, idata, isize);
if (!cbw.exist)
{
cbw.output = cbw.output + name + xsfc::TString(L"=") + value + xsfc::TString(L"\n");
}
xsfc::TStringM oututf8(true, cbw.output);
cfg_fooxsf = oututf8;
}
xsfc::TString GetConfigValue(const wchar_t *name)
{
xsfc::TStringM tag(true, name);
const char *idata = cfg_fooxsf.get_ptr();
size_t isize = xsfc::StrNLen<char>(idata);
return XSFTag::GetRaw(true, tag, idata, isize);
}
public:
foo_config()
{
}
~foo_config()
{
}
void SetULong(const wchar_t *name, const unsigned long value) throw()
{
try
{
xsfc::TString sValue(value);
SetConfigValue(name, sValue);
}
catch (xsfc::EShortOfMemory e)
{
}
}
unsigned long GetULong(const wchar_t *name, const unsigned long defaultvalue = 0) throw()
{
try
{
xsfc::TString value = GetConfigValue(name);
if (value[0])
return value.GetULong();
}
catch (xsfc::EShortOfMemory e)
{
}
return defaultvalue;
}
void SetFloat(const wchar_t *name, const double value) throw()
{
try
{
xsfc::TString sValue(value);
SetConfigValue(name, sValue);
}
catch (xsfc::EShortOfMemory e)
{
}
}
double GetFloat(const wchar_t *name, const double defaultvalue = 0) throw()
{
try
{
xsfc::TString value = GetConfigValue(name);
if (value[0])
return value.GetFloat();
}
catch (xsfc::EShortOfMemory e)
{
}
return defaultvalue;
}
void SetString(const wchar_t *name, const wchar_t *value) throw()
{
try
{
xsfc::TString sValue(value);
SetConfigValue(name, sValue);
}
catch (xsfc::EShortOfMemory e)
{
}
}
xsfc::TString GetString(const wchar_t *name, const wchar_t *defaultvalue = 0) throw()
{
try
{
xsfc::TString value = GetConfigValue(name);
if (value[0])
return value;
}
catch (xsfc::EShortOfMemory e)
{
}
return defaultvalue;
}
};
static foo_config icfg;
class foo_input_xsfcfg : public preferences_page_v2
{
protected:
bool initialized;
foo_config *pcfg;
HWND hwnd;
bool OnCommand(HWND hwndDlg, DWORD id, DWORD cmd)
{
switch (id)
{
case 0x200: case 0x201: case 0x202:
case 0x203: case 0x204: case 0x205:
if (initialized)
{
CFGUpdate(pcfg, hwndDlg);
CFGSave(pcfg);
}
break;
case 0x206:
if (cmd == LBN_SELCHANGE)
{
CFGMuteChange(hwndDlg, 0x206);
}
break;
default:
break;
}
return FALSE;
}
bool OnInit(HWND hwndDlg)
{
hwnd = hwndDlg;
pcfg = &icfg;
xsfc::TWin32::WndSetLongPtr(hwndDlg, DWLP_USER, this);
initialized = false;
CFGReset(pcfg, hwndDlg);
initialized = true;
return TRUE;
}
static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
{
foo_input_xsfcfg *pthis = static_cast<foo_input_xsfcfg *>(xsfc::TWin32::WndGetLongPtr(hwndDlg, DWLP_USER));
return pthis->OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam));
}
case WM_INITDIALOG:
{
foo_input_xsfcfg *pthis = static_cast<foo_input_xsfcfg *>((void *)lParam);
return pthis->OnInit(hwndDlg) ? TRUE : FALSE;
}
}
return FALSE;
}
public:
HWND create(HWND p_parent)
{
return static_cast<HWND>(xsfc::TWin32::DlgCreate(hDLL, 1, p_parent, DialogProc, this));
}
const char * get_name() { return XSFDRIVER_SIMPLENAME; }
GUID get_guid() { return cfgguid1; }
GUID get_parent_guid() { return guid_input; }
bool reset_query() { return true; }
void reset()
{
CFGDefault();
CFGReset(pcfg, hwnd);
CFGSave(pcfg);
}
bool get_help_url(pfc::string_base & p_out) { return false; }
double get_sort_priority() { return 0; }
foo_input_xsfcfg()
: initialized(false)
{
}
~foo_input_xsfcfg()
{
}
};
class foo_initquit : public initquit
{
void on_init()
{
CFGLoad(&icfg);
}
void on_quit()
{
}
};
static preferences_page_factory_t<foo_input_xsfcfg> g_input_xsfcfg_factory;
static initquit_factory_t<foo_initquit> g_input_xsfiq_factory;
}
extern "C" void fb2k_config_init(HINSTANCE hinstDLL)
{
hDLL = (HMODULE)hinstDLL;
}

View File

@ -0,0 +1,255 @@
#include "foobar2000/SDK/foobar2000.h"
#include "../pversion.h"
#include "tagget.h"
#include "xsfcfg.h"
namespace
{
HMODULE hDLL;
cfg_string cfg_fooxsf(XSFDRIVER_SIMPLENAME "/config", "");
class foo_config : public IConfigIO
{
protected:
typedef struct
{
xsfc::TString output;
xsfc::TString newvalue;
xsfc::TStringM newname;
size_t newnamelen;
bool exist;
}
cbw_t;
static enum XSFTag::enum_callback_returnvalue scv_cb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd)
{
cbw_t *pcbw = static_cast<cbw_t *>(pWork);
xsfc::TString name(true, pNameTop, pNameEnd - pNameTop);
if (pcbw->newnamelen == unsigned(pNameEnd - pNameTop) && !_strnicmp(pNameTop, pcbw->newname, pcbw->newnamelen))
{
pcbw->exist = true;
pcbw->output = pcbw->output + name + xsfc::TString(L"=") + pcbw->newvalue + xsfc::TString(L"\n");
}
else
{
xsfc::TString value(true, pValueTop, pValueEnd - pValueTop);
pcbw->output = pcbw->output + name + xsfc::TString(L"=") + value + xsfc::TString(L"\n");
}
return XSFTag::enum_continue;
}
void SetConfigValue(const wchar_t *name, xsfc::TString value)
{
const char *idata = cfg_fooxsf.get_val();
size_t isize = xsfc::StrNLen<char>(idata);
cbw_t cbw;
cbw.newvalue = value;
cbw.newname = xsfc::TStringM(true, name);
cbw.newnamelen = xsfc::StrNLen<char>(cbw.newname);
cbw.exist = false;
XSFTag::EnumRaw(scv_cb, &cbw, idata, isize);
if (!cbw.exist)
{
cbw.output = cbw.output + name + xsfc::TString(L"=") + value + xsfc::TString(L"\n");
}
xsfc::TStringM oututf8(true, cbw.output);
cfg_fooxsf = oututf8;
}
xsfc::TString GetConfigValue(const wchar_t *name)
{
xsfc::TStringM tag(true, name);
const char *idata = cfg_fooxsf.get_val();
size_t isize = xsfc::StrNLen<char>(idata);
return XSFTag::GetRaw(true, tag, idata, isize);
}
public:
foo_config()
{
}
~foo_config()
{
}
void SetULong(const wchar_t *name, const unsigned long value) throw()
{
try
{
xsfc::TString sValue(value);
SetConfigValue(name, sValue);
}
catch (xsfc::EShortOfMemory e)
{
}
}
unsigned long GetULong(const wchar_t *name, const unsigned long defaultvalue = 0) throw()
{
try
{
xsfc::TString value = GetConfigValue(name);
if (value[0])
return value.GetULong();
}
catch (xsfc::EShortOfMemory e)
{
}
return defaultvalue;
}
void SetFloat(const wchar_t *name, const double value) throw()
{
try
{
xsfc::TString sValue(value);
SetConfigValue(name, sValue);
}
catch (xsfc::EShortOfMemory e)
{
}
}
double GetFloat(const wchar_t *name, const double defaultvalue = 0) throw()
{
try
{
xsfc::TString value = GetConfigValue(name);
if (value[0])
return value.GetFloat();
}
catch (xsfc::EShortOfMemory e)
{
}
return defaultvalue;
}
void SetString(const wchar_t *name, const wchar_t *value) throw()
{
try
{
xsfc::TString sValue(value);
SetConfigValue(name, sValue);
}
catch (xsfc::EShortOfMemory e)
{
}
}
xsfc::TString GetString(const wchar_t *name, const wchar_t *defaultvalue = 0)
{
try
{
xsfc::TString value = GetConfigValue(name);
if (value[0])
return value;
}
catch (xsfc::EShortOfMemory e)
{
}
return defaultvalue;
}
};
static foo_config icfg;
class foo_input_xsfcfg : public config
{
protected:
bool initialized;
foo_config *pcfg;
HWND hwnd;
bool OnCommand(HWND hwndDlg, DWORD id, DWORD cmd)
{
switch (id)
{
case 0x200: case 0x201: case 0x202:
case 0x203: case 0x204: case 0x205:
if (initialized)
{
CFGUpdate(pcfg, hwndDlg);
CFGSave(pcfg);
}
break;
case 0x206:
if (cmd == LBN_SELCHANGE)
{
CFGMuteChange(hwndDlg, 0x206);
}
break;
default:
break;
}
return FALSE;
}
bool OnInit(HWND hwndDlg)
{
hwnd = hwndDlg;
pcfg = &icfg;
xsfc::TWin32::WndSetLongPtr(hwndDlg, DWL_USER, this);
initialized = false;
CFGReset(pcfg, hwndDlg);
initialized = true;
return TRUE;
}
static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
{
foo_input_xsfcfg *pthis = static_cast<foo_input_xsfcfg *>(xsfc::TWin32::WndGetLongPtr(hwndDlg, DWL_USER));
return pthis->OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam));
}
case WM_INITDIALOG:
{
foo_input_xsfcfg *pthis = static_cast<foo_input_xsfcfg *>((void *)lParam);
return pthis->OnInit(hwndDlg) ? TRUE : FALSE;
}
}
return FALSE;
}
public:
HWND create(HWND p_parent)
{
return (HWND)xsfc::TWin32::DlgCreate(hDLL, 1, p_parent, DialogProc, this);
}
const char * get_name() { return XSFDRIVER_SIMPLENAME; }
const char * get_parent_name() {return "Input";}
foo_input_xsfcfg()
: initialized(false)
{
}
~foo_input_xsfcfg()
{
}
};
class foo_initquit : public initquit
{
void on_init()
{
CFGLoad(&icfg);
}
void on_quit()
{
}
};
static config_factory<foo_input_xsfcfg> g_input_xsfcfg_factory;
static initquit_factory<foo_initquit> g_input_xsfiq_factory;
}
extern "C" void fb2k_config_init(HINSTANCE hinstDLL)
{
hDLL = (HMODULE)hinstDLL;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,291 @@
#define WIN32_LEAN_AND_MEAN
#include "leakchk.h"
#include <windows.h>
#include <windowsx.h>
/* Winamp SDK headers */
#include <winamp/wa_ipc.h>
#include "../pversion.h"
#include "in_xsfcfg.h"
#include "xsfui.rh"
#if _MSC_VER >= 1200
#pragma warning(disable:4290)
#endif
extern unsigned long dwInterpolation;
namespace
{
xsfc::TAutoPtr<IConfigIO> pcfg;
prefsDlgRec prefwork;
int prefreg = 0;
HMODULE hDLL = 0;
}
class IniConfig : public IConfigIO
{
xsfc::TString sIniPath;
protected:
IniConfig() throw()
{
}
bool Initialize(HWND hwndWinamp) throw(xsfc::EShortOfMemory)
{
char *ini = (char *)(::SendMessageA(hwndWinamp, WM_WA_IPC, 0, IPC_GETINIFILE));
if (ini && int(ini) != 1 && !IsBadStringPtrA(ini, MAX_PATH))
sIniPath = xsfc::TString(ini);
else
sIniPath = xsfc::TWin32::ExtractPath(xsfc::TWin32::ModulePath(NULL)) + "winamp.ini";
return true;
}
public:
~IniConfig() throw()
{
}
void SetULong(const wchar_t *name, const unsigned long value) throw()
{
try
{
xsfc::TWin32::SetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, xsfc::TString(value));
}
catch (xsfc::EShortOfMemory e)
{
}
}
unsigned long GetULong(const wchar_t *name, const unsigned long defaultvalue = 0) throw()
{
try
{
xsfc::TString value = xsfc::TWin32::GetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, xsfc::TString(defaultvalue));
if (value[0]) return value.GetULong();
}
catch (xsfc::EShortOfMemory e)
{
}
return defaultvalue;
}
void SetFloat(const wchar_t *name, const double value) throw()
{
try
{
xsfc::TWin32::SetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, xsfc::TString(value));
}
catch (xsfc::EShortOfMemory e)
{
}
}
double GetFloat(const wchar_t *name, const double defaultvalue = 0) throw()
{
try
{
xsfc::TString value = xsfc::TWin32::GetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, xsfc::TString(defaultvalue));
if (value[0]) return value.GetFloat();
}
catch (xsfc::EShortOfMemory e)
{
}
return defaultvalue;
}
void SetString(const wchar_t *name, const wchar_t *value) throw()
{
try
{
xsfc::TWin32::SetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, value);
}
catch (xsfc::EShortOfMemory e)
{
}
}
xsfc::TString GetString(const wchar_t *name, const wchar_t *defaultvalue = 0) throw(xsfc::EShortOfMemory)
{
return xsfc::TWin32::GetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, defaultvalue);
}
static LPIConfigIO Create(HWND hwndWinamp) throw(xsfc::EShortOfMemory)
{
xsfc::TAutoPtr<IniConfig> cfg(new(xsfc::nothrow) IniConfig);
return (cfg && cfg->Initialize(hwndWinamp)) ? cfg.Detach() : 0;
}
};
static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_COMBO_INTERPOLATION:
if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
{
dwInterpolation = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION));
}
break;
case IDOK:
CFGUpdate(pcfg, hwndDlg);
CFGSave(pcfg);
::EndDialog(hwndDlg, IDOK);
break;
case IDCANCEL:
::EndDialog(hwndDlg, IDCANCEL);
break;
case 0x206:
if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE)
{
CFGMuteChange(hwndDlg, 0x206);
}
break;
default:
return FALSE;
}
break;
case WM_INITDIALOG:
::SetWindowTextA(hwndDlg, WINAMPPLUGIN_NAME);
::ShowWindow(GetDlgItem(hwndDlg, IDOK), SW_SHOWNA);
::ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_SHOWNA);
ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "None");
ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "Linear");
ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "Cosine");
ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), dwInterpolation);
CFGLoad(pcfg);
CFGReset(pcfg, hwndDlg);
return TRUE;
}
return FALSE;
}
static BOOL CALLBACK DialogProcPref(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static bool initialized = false;
switch (uMsg)
{
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, LpARAM))
{
case IDC_COMBO_INTERPOLATION:
if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
{
dwInterpolation = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION));
CFGSave(pcfg);
}
break;
case 0x200: case 0x201: case 0x202:
case 0x203: case 0x204: case 0x205:
if (initialized)
{
CFGUpdate(pcfg, hwndDlg);
CFGSave(pcfg);
}
break;
case 0x206:
if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE)
{
CFGMuteChange(hwndDlg, 0x206);
}
break;
default:
return FALSE;
}
break;
case WM_INITDIALOG:
initialized = false;
ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "None");
ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "Linear");
ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "Cosine");
CFGLoad(pcfg);
CFGReset(pcfg, hwndDlg);
initialized = true;
return TRUE;
}
return FALSE;
}
void winamp_config_init(HINSTANCE hinstDLL)
{
hDLL = hinstDLL;
}
void winamp_config_load(HWND hwndWinamp)
{
if (!pcfg)
{
pcfg = IniConfig::Create(hwndWinamp);
if (!pcfg) pcfg = NullConfig::Create();
CFGLoad(pcfg);
}
}
void winamp_config_add_prefs(HWND hwndWinamp)
{
if (prefreg) return;
if (((LONG)xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, 0, IPC_GETVERSION) & 0xffffU) >= 0x2090)
{
/* 2.9+ */
prefwork.hInst = hDLL;
prefwork.dlgID = 1;
prefwork.proc = (void *)DialogProcPref;
prefwork.name = XSFDRIVER_SIMPLENAME;
prefwork.where = 0;
prefwork._id = 0;
prefwork.next = 0;
prefreg = !(LONG)xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, &prefwork, IPC_ADD_PREFS_DLG);
}
}
void winamp_config_remove_prefs(HWND hwndWinamp)
{
if (pcfg) pcfg.Release();
if (prefreg)
{
xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, &prefwork, IPC_REMOVE_PREFS_DLG);
prefreg = 0;
}
}
void winamp_config_dialog(HWND hwndWinamp, HWND hwndParent)
{
HRSRC hrsrc;
DWORD dwSize;
HGLOBAL hGlobal;
xsfc::TSimpleArray<BYTE> resbuf;
if (prefreg)
{
if (((LONG)xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, 0, IPC_GETVERSION) & 0xffffU) >= 0x5000)
{
xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, &prefwork, IPC_OPENPREFSTOPAGE);
return;
}
}
hrsrc = ::FindResourceA(hDLL, MAKEINTRESOURCE(1), RT_DIALOG);
if (!hrsrc) return;
dwSize = ::SizeofResource(hDLL, hrsrc);
hGlobal = ::LoadResource(hDLL, hrsrc);
if (dwSize < 4 || !hGlobal) return;
if (!resbuf.Resize(dwSize)) return;
LPBYTE lpResource = resbuf.Ptr();
::CopyMemory(lpResource, hGlobal, dwSize);
lpResource[0] = '\xc0';
lpResource[1] = '\x08';
lpResource[2] = '\xc8';
lpResource[3] = '\x80';
xsfc::TWin32::DlgInvoke(::GetModuleHandleA(NULL), lpResource, NULL, DialogProc, NULL);
}

View File

@ -0,0 +1,17 @@
#include "xsfcfg.h"
#ifdef __cplusplus
extern "C"
{
#endif
void winamp_config_init(HINSTANCE hinstDLL);
void winamp_config_load(HWND hwndWinamp);
void winamp_config_add_prefs(HWND hwndWinamp);
void winamp_config_remove_prefs(HWND hwndWinamp);
void winamp_config_dialog(HWND hwndWinamp, HWND hwndParent);
#ifdef __cplusplus
}
#endif

Some files were not shown because too many files have changed in this diff Show More