tools: add vio2sf; enable mute channels and add interpolation choice
This commit is contained in:
parent
2ef411f641
commit
ec367f17be
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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) */
|
||||
/* 1ファイル複数曲(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 時に動作終了は不可) */
|
||||
/* */
|
||||
/* 上記以外で対応拡張子が1つもない場合、不正なプラグインと見なされ、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 を返すこと。 */
|
||||
/* */
|
||||
/* 1ファイル複数曲(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
|
||||
|
|
@ -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!
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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"
|
|
@ -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
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
@ -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
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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__*/
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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__*/
|
|
@ -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
|
|
@ -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
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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__*/
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
@ -0,0 +1,2 @@
|
|||
ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
|
||||
ml64.exe /Flgvmat64 /c /Zi gvmat64.asm
|
|
@ -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
|
Binary file not shown.
|
@ -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
|
|
@ -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
|
Binary file not shown.
|
@ -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)
|
|
@ -0,0 +1,2 @@
|
|||
ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm
|
||||
ml /coff /Zi /c /Flinffas32.lst inffas32.asm
|
|
@ -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 ; can’t 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 ; can’t 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
|
Binary file not shown.
|
@ -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
Binary file not shown.
|
@ -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
|
|
@ -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"
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
}
|
||||
};
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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));
|
|
@ -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
|
@ -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 */
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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));
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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);
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue