summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ShizZy2013-09-04 20:17:46 -0400
committerGravatar ShizZy2013-09-04 20:17:46 -0400
commit7564d28faf780bc0967ab3f6ff11b29b44e4b1aa (patch)
tree48c87985296d0bc8d62785b8f3209f4b727d0cc0
parentdeleted gekko's common files (diff)
downloadyuzu-7564d28faf780bc0967ab3f6ff11b29b44e4b1aa.tar.gz
yuzu-7564d28faf780bc0967ab3f6ff11b29b44e4b1aa.tar.xz
yuzu-7564d28faf780bc0967ab3f6ff11b29b44e4b1aa.zip
replaced common code with dolphin common
-rw-r--r--akiru.sln56
-rw-r--r--src/common/common.vcxproj185
-rw-r--r--src/common/common.vcxproj.filters68
-rw-r--r--src/common/src/atomic.h19
-rw-r--r--src/common/src/atomic_gcc.h113
-rw-r--r--src/common/src/atomic_win32.h72
-rw-r--r--src/common/src/break_points.cpp203
-rw-r--r--src/common/src/break_points.h102
-rw-r--r--src/common/src/chunk_file.h384
-rw-r--r--src/common/src/common.h164
-rw-r--r--src/common/src/common_funcs.h243
-rw-r--r--src/common/src/common_paths.h71
-rw-r--r--src/common/src/common_types.h48
-rw-r--r--src/common/src/console_listener.cpp337
-rw-r--r--src/common/src/console_listener.h41
-rw-r--r--src/common/src/cpu_detect.h81
-rw-r--r--src/common/src/debug_interface.h39
-rw-r--r--src/common/src/extended_trace.cpp433
-rw-r--r--src/common/src/extended_trace.h53
-rw-r--r--src/common/src/fifo_queue.h115
-rw-r--r--src/common/src/file_search.cpp106
-rw-r--r--src/common/src/file_search.h28
-rw-r--r--src/common/src/file_util.cpp922
-rw-r--r--src/common/src/file_util.h232
-rw-r--r--src/common/src/fixed_size_queue.h75
-rw-r--r--src/common/src/hash.cpp520
-rw-r--r--src/common/src/hash.h20
-rw-r--r--src/common/src/linear_disk_cache.h191
-rw-r--r--src/common/src/log.h155
-rw-r--r--src/common/src/log_manager.cpp199
-rw-r--r--src/common/src/log_manager.h169
-rw-r--r--src/common/src/math_util.cpp212
-rw-r--r--src/common/src/math_util.h200
-rw-r--r--src/common/src/mem_arena.cpp304
-rw-r--r--src/common/src/mem_arena.h58
-rw-r--r--src/common/src/memory_util.cpp197
-rw-r--r--src/common/src/memory_util.h25
-rw-r--r--src/common/src/misc.cpp33
-rw-r--r--src/common/src/msg_handler.cpp107
-rw-r--r--src/common/src/msg_handler.h73
-rw-r--r--src/common/src/scm_rev.h4
-rw-r--r--src/common/src/std_condition_variable.h170
-rw-r--r--src/common/src/std_mutex.h365
-rw-r--r--src/common/src/std_thread.h317
-rw-r--r--src/common/src/string_util.cpp531
-rw-r--r--src/common/src/string_util.h111
-rw-r--r--src/common/src/thread.cpp133
-rw-r--r--src/common/src/thread.h156
-rw-r--r--src/common/src/thunk.h46
-rw-r--r--src/common/src/timer.cpp226
-rw-r--r--src/common/src/timer.h46
-rw-r--r--src/common/src/version.cpp45
-rw-r--r--vsprops/code_generation_debug.props (renamed from vsprops/CodeGen_Debug.props)0
-rw-r--r--vsprops/code_generation_release.props (renamed from vsprops/CodeGen_Release.props)0
54 files changed, 8640 insertions, 163 deletions
diff --git a/akiru.sln b/akiru.sln
index 47fbc7bf9..c8bf30000 100644
--- a/akiru.sln
+++ b/akiru.sln
@@ -1,23 +1,7 @@
1Microsoft Visual Studio Solution File, Format Version 11.00 1Microsoft Visual Studio Solution File, Format Version 11.00
2# Visual Studio 2010 2# Visual Studio 2010
3Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "akiru_qt", "src\akiru_qt\akiru_qt.vcxproj", "{A587F714-490F-407A-9E36-7AB7FA0D7BAB}"
4 ProjectSection(ProjectDependencies) = postProject
5 {8AEA7F29-3466-4786-A10D-6A4BD0610977} = {8AEA7F29-3466-4786-A10D-6A4BD0610977}
6 {6678D1A3-33A6-48A9-878B-48E5D2903D27} = {6678D1A3-33A6-48A9-878B-48E5D2903D27}
7 {E34D07D0-7DE6-4C46-A00D-C20C691789E4} = {E34D07D0-7DE6-4C46-A00D-C20C691789E4}
8 {DFE335FC-755D-4BAA-8452-94434F8A1EDB} = {DFE335FC-755D-4BAA-8452-94434F8A1EDB}
9 EndProjectSection
10EndProject
11Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "src\core\core.vcxproj", "{8AEA7F29-3466-4786-A10D-6A4BD0610977}"
12 ProjectSection(ProjectDependencies) = postProject
13 {6678D1A3-33A6-48A9-878B-48E5D2903D27} = {6678D1A3-33A6-48A9-878B-48E5D2903D27}
14 {E34D07D0-7DE6-4C46-A00D-C20C691789E4} = {E34D07D0-7DE6-4C46-A00D-C20C691789E4}
15 EndProjectSection
16EndProject
17Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "src\common\common.vcxproj", "{DFE335FC-755D-4BAA-8452-94434F8A1EDB}" 3Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "src\common\common.vcxproj", "{DFE335FC-755D-4BAA-8452-94434F8A1EDB}"
18EndProject 4EndProject
19Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "akiru", "src\akiru\akiru.vcxproj", "{CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}"
20EndProject
21Global 5Global
22 GlobalSection(SolutionConfigurationPlatforms) = preSolution 6 GlobalSection(SolutionConfigurationPlatforms) = preSolution
23 Debug|Win32 = Debug|Win32 7 Debug|Win32 = Debug|Win32
@@ -26,22 +10,6 @@ Global
26 Release|x64 = Release|x64 10 Release|x64 = Release|x64
27 EndGlobalSection 11 EndGlobalSection
28 GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 GlobalSection(ProjectConfigurationPlatforms) = postSolution
29 {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Debug|Win32.ActiveCfg = Debug|Win32
30 {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Debug|Win32.Build.0 = Debug|Win32
31 {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Debug|x64.ActiveCfg = Debug|x64
32 {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Debug|x64.Build.0 = Debug|x64
33 {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|Win32.ActiveCfg = Release|Win32
34 {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|Win32.Build.0 = Release|Win32
35 {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|x64.ActiveCfg = Release|x64
36 {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|x64.Build.0 = Release|x64
37 {8AEA7F29-3466-4786-A10D-6A4BD0610977}.Debug|Win32.ActiveCfg = Debug|Win32
38 {8AEA7F29-3466-4786-A10D-6A4BD0610977}.Debug|Win32.Build.0 = Debug|Win32
39 {8AEA7F29-3466-4786-A10D-6A4BD0610977}.Debug|x64.ActiveCfg = Debug|x64
40 {8AEA7F29-3466-4786-A10D-6A4BD0610977}.Debug|x64.Build.0 = Debug|x64
41 {8AEA7F29-3466-4786-A10D-6A4BD0610977}.Release|Win32.ActiveCfg = Release|Win32
42 {8AEA7F29-3466-4786-A10D-6A4BD0610977}.Release|Win32.Build.0 = Release|Win32
43 {8AEA7F29-3466-4786-A10D-6A4BD0610977}.Release|x64.ActiveCfg = Release|x64
44 {8AEA7F29-3466-4786-A10D-6A4BD0610977}.Release|x64.Build.0 = Release|x64
45 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Debug|Win32.ActiveCfg = Debug|Win32 13 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Debug|Win32.ActiveCfg = Debug|Win32
46 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Debug|Win32.Build.0 = Debug|Win32 14 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Debug|Win32.Build.0 = Debug|Win32
47 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Debug|x64.ActiveCfg = Debug|x64 15 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Debug|x64.ActiveCfg = Debug|x64
@@ -50,30 +18,6 @@ Global
50 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Release|Win32.Build.0 = Release|Win32 18 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Release|Win32.Build.0 = Release|Win32
51 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Release|x64.ActiveCfg = Release|x64 19 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Release|x64.ActiveCfg = Release|x64
52 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Release|x64.Build.0 = Release|x64 20 {DFE335FC-755D-4BAA-8452-94434F8A1EDB}.Release|x64.Build.0 = Release|x64
53 {E34D07D0-7DE6-4C46-A00D-C20C691789E4}.Debug|Win32.ActiveCfg = Debug|Win32
54 {E34D07D0-7DE6-4C46-A00D-C20C691789E4}.Debug|Win32.Build.0 = Debug|Win32
55 {E34D07D0-7DE6-4C46-A00D-C20C691789E4}.Debug|x64.ActiveCfg = Debug|x64
56 {E34D07D0-7DE6-4C46-A00D-C20C691789E4}.Debug|x64.Build.0 = Debug|x64
57 {E34D07D0-7DE6-4C46-A00D-C20C691789E4}.Release|Win32.ActiveCfg = Release|Win32
58 {E34D07D0-7DE6-4C46-A00D-C20C691789E4}.Release|Win32.Build.0 = Release|Win32
59 {E34D07D0-7DE6-4C46-A00D-C20C691789E4}.Release|x64.ActiveCfg = Release|x64
60 {E34D07D0-7DE6-4C46-A00D-C20C691789E4}.Release|x64.Build.0 = Release|x64
61 {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Debug|Win32.ActiveCfg = Debug|Win32
62 {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Debug|Win32.Build.0 = Debug|Win32
63 {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Debug|x64.ActiveCfg = Debug|x64
64 {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Debug|x64.Build.0 = Debug|x64
65 {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Release|Win32.ActiveCfg = Release|Win32
66 {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Release|Win32.Build.0 = Release|Win32
67 {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Release|x64.ActiveCfg = Release|x64
68 {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Release|x64.Build.0 = Release|x64
69 {CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}.Debug|Win32.ActiveCfg = Debug|Win32
70 {CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}.Debug|Win32.Build.0 = Debug|Win32
71 {CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}.Debug|x64.ActiveCfg = Debug|x64
72 {CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}.Debug|x64.Build.0 = Debug|x64
73 {CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}.Release|Win32.ActiveCfg = Release|Win32
74 {CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}.Release|Win32.Build.0 = Release|Win32
75 {CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}.Release|x64.ActiveCfg = Release|x64
76 {CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}.Release|x64.Build.0 = Release|x64
77 EndGlobalSection 21 EndGlobalSection
78 GlobalSection(SolutionProperties) = preSolution 22 GlobalSection(SolutionProperties) = preSolution
79 HideSolutionNode = FALSE 23 HideSolutionNode = FALSE
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index c61ba6d9d..1cfe0bb37 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -1,6 +1,14 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 2<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <ItemGroup Label="ProjectConfigurations"> 3 <ItemGroup Label="ProjectConfigurations">
4 <ProjectConfiguration Include="DebugFast|Win32">
5 <Configuration>DebugFast</Configuration>
6 <Platform>Win32</Platform>
7 </ProjectConfiguration>
8 <ProjectConfiguration Include="DebugFast|x64">
9 <Configuration>DebugFast</Configuration>
10 <Platform>x64</Platform>
11 </ProjectConfiguration>
4 <ProjectConfiguration Include="Debug|Win32"> 12 <ProjectConfiguration Include="Debug|Win32">
5 <Configuration>Debug</Configuration> 13 <Configuration>Debug</Configuration>
6 <Platform>Win32</Platform> 14 <Platform>Win32</Platform>
@@ -20,102 +28,82 @@
20 </ItemGroup> 28 </ItemGroup>
21 <PropertyGroup Label="Globals"> 29 <PropertyGroup Label="Globals">
22 <ProjectGuid>{DFE335FC-755D-4BAA-8452-94434F8A1EDB}</ProjectGuid> 30 <ProjectGuid>{DFE335FC-755D-4BAA-8452-94434F8A1EDB}</ProjectGuid>
23 <RootNamespace>common</RootNamespace> 31 <RootNamespace>Common</RootNamespace>
24 </PropertyGroup> 32 </PropertyGroup>
25 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 33 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
26 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> 34 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
27 <UseDebugLibraries>true</UseDebugLibraries> 35 <UseDebugLibraries>true</UseDebugLibraries>
28 <ConfigurationType>StaticLibrary</ConfigurationType> 36 <ConfigurationType>StaticLibrary</ConfigurationType>
37 <CharacterSet>MultiByte</CharacterSet>
29 </PropertyGroup> 38 </PropertyGroup>
30 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> 39 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
31 <ConfigurationType>StaticLibrary</ConfigurationType>
32 <UseDebugLibraries>true</UseDebugLibraries> 40 <UseDebugLibraries>true</UseDebugLibraries>
41 <ConfigurationType>StaticLibrary</ConfigurationType>
42 <CharacterSet>MultiByte</CharacterSet>
33 </PropertyGroup> 43 </PropertyGroup>
34 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> 44 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
45 <UseDebugLibraries>false</UseDebugLibraries>
46 <ConfigurationType>StaticLibrary</ConfigurationType>
47 <CharacterSet>Unicode</CharacterSet>
48 </PropertyGroup>
49 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
35 <ConfigurationType>StaticLibrary</ConfigurationType> 50 <ConfigurationType>StaticLibrary</ConfigurationType>
36 <UseDebugLibraries>false</UseDebugLibraries> 51 <UseDebugLibraries>false</UseDebugLibraries>
52 <CharacterSet>MultiByte</CharacterSet>
37 </PropertyGroup> 53 </PropertyGroup>
38 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> 54 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
55 <UseDebugLibraries>false</UseDebugLibraries>
56 <ConfigurationType>StaticLibrary</ConfigurationType>
57 <CharacterSet>Unicode</CharacterSet>
58 </PropertyGroup>
59 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
39 <ConfigurationType>StaticLibrary</ConfigurationType> 60 <ConfigurationType>StaticLibrary</ConfigurationType>
40 <UseDebugLibraries>false</UseDebugLibraries> 61 <UseDebugLibraries>false</UseDebugLibraries>
62 <CharacterSet>MultiByte</CharacterSet>
41 </PropertyGroup> 63 </PropertyGroup>
42 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 64 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
43 <ImportGroup Label="ExtensionSettings"> 65 <ImportGroup Label="ExtensionSettings">
44 </ImportGroup> 66 </ImportGroup>
45 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 67 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
46 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 68 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
47 <Import Project="..\..\vsprops\Base.props" /> 69 <Import Project="..\..\vsprops\base.props" />
48 <Import Project="..\..\vsprops\CodeGen_Debug.props" /> 70 <Import Project="..\..\vsprops\code_generation_debug.props" />
49 <Import Project="..\..\vsprops\Optimization_Debug.props" />
50 <Import Project="..\..\vsprops\Externals.props" />
51 </ImportGroup> 71 </ImportGroup>
52 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> 72 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
53 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 73 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
54 <Import Project="..\..\vsprops\Base.props" /> 74 <Import Project="..\..\vsprops\base.props" />
55 <Import Project="..\..\vsprops\CodeGen_Debug.props" /> 75 <Import Project="..\..\vsprops\code_generation_debug.props" />
56 <Import Project="..\..\vsprops\Optimization_Debug.props" />
57 <Import Project="..\..\vsprops\Externals.props" />
58 </ImportGroup> 76 </ImportGroup>
59 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 77 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
60 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 78 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
61 <Import Project="..\..\vsprops\Base.props" /> 79 <Import Project="..\..\vsprops\base.props" />
62 <Import Project="..\..\vsprops\CodeGen_Release.props" /> 80 <Import Project="..\..\vsprops\code_generation_release.props" />
63 <Import Project="..\..\vsprops\Optimization_Release.props" />
64 <Import Project="..\..\vsprops\Externals.props" />
65 </ImportGroup> 81 </ImportGroup>
66 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> 82 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
67 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 83 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
68 <Import Project="..\..\vsprops\Base.props" /> 84 <Import Project="..\..\vsprops\base.props" />
69 <Import Project="..\..\vsprops\CodeGen_Release.props" /> 85 <Import Project="..\..\vsprops\code_generation_release.props" />
70 <Import Project="..\..\vsprops\Optimization_Release.props" />
71 <Import Project="..\..\vsprops\Externals.props" />
72 </ImportGroup> 86 </ImportGroup>
73 <PropertyGroup Label="UserMacros" /> 87 <PropertyGroup Label="UserMacros" />
74 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> 88 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
75 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
76 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
77 <CustomBuildBeforeTargets>
78 </CustomBuildBeforeTargets>
79 </PropertyGroup>
80 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
81 <CustomBuildBeforeTargets />
82 </PropertyGroup>
83 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> 89 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
90 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" />
91 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
84 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" /> 92 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
85 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 93 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
86 <CustomBuildBeforeTargets>
87 </CustomBuildBeforeTargets>
88 </PropertyGroup>
89 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
90 <CustomBuildBeforeTargets />
91 </PropertyGroup>
92 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 94 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
93 <ClCompile /> 95 <ClCompile />
94 <Link> 96 <Link>
95 <GenerateDebugInformation>true</GenerateDebugInformation> 97 <GenerateDebugInformation>true</GenerateDebugInformation>
96 </Link> 98 </Link>
97 <CustomBuildStep> 99 <Lib />
98 <Command>
99 </Command>
100 <Message>
101 </Message>
102 <Outputs>
103 </Outputs>
104 </CustomBuildStep>
105 </ItemDefinitionGroup> 100 </ItemDefinitionGroup>
106 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> 101 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
107 <ClCompile /> 102 <ClCompile />
108 <Link> 103 <Link>
109 <GenerateDebugInformation>true</GenerateDebugInformation> 104 <GenerateDebugInformation>true</GenerateDebugInformation>
110 </Link> 105 </Link>
111 <CustomBuildStep> 106 <Lib />
112 <Command>
113 </Command>
114 <Message>
115 </Message>
116 <Outputs>
117 </Outputs>
118 </CustomBuildStep>
119 </ItemDefinitionGroup> 107 </ItemDefinitionGroup>
120 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 108 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
121 <ClCompile /> 109 <ClCompile />
@@ -124,15 +112,16 @@
124 <EnableCOMDATFolding>true</EnableCOMDATFolding> 112 <EnableCOMDATFolding>true</EnableCOMDATFolding>
125 <OptimizeReferences>true</OptimizeReferences> 113 <OptimizeReferences>true</OptimizeReferences>
126 </Link> 114 </Link>
127 <CustomBuildStep> 115 <Lib />
128 <Command> 116 </ItemDefinitionGroup>
129 </Command> 117 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
130 <Message>
131 </Message>
132 <Outputs>
133 </Outputs>
134 </CustomBuildStep>
135 <ClCompile /> 118 <ClCompile />
119 <Link>
120 <GenerateDebugInformation>true</GenerateDebugInformation>
121 <EnableCOMDATFolding>true</EnableCOMDATFolding>
122 <OptimizeReferences>true</OptimizeReferences>
123 </Link>
124 <Lib />
136 </ItemDefinitionGroup> 125 </ItemDefinitionGroup>
137 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> 126 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
138 <ClCompile /> 127 <ClCompile />
@@ -141,46 +130,72 @@
141 <EnableCOMDATFolding>true</EnableCOMDATFolding> 130 <EnableCOMDATFolding>true</EnableCOMDATFolding>
142 <OptimizeReferences>true</OptimizeReferences> 131 <OptimizeReferences>true</OptimizeReferences>
143 </Link> 132 </Link>
144 <CustomBuildStep> 133 <Lib />
145 <Command> 134 </ItemDefinitionGroup>
146 </Command> 135 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
147 <Message> 136 <ClCompile />
148 </Message> 137 <Link>
149 <Outputs> 138 <GenerateDebugInformation>true</GenerateDebugInformation>
150 </Outputs> 139 <EnableCOMDATFolding>true</EnableCOMDATFolding>
151 </CustomBuildStep> 140 <OptimizeReferences>true</OptimizeReferences>
141 </Link>
142 <Lib />
152 </ItemDefinitionGroup> 143 </ItemDefinitionGroup>
153 <ItemGroup>
154 <ClCompile Include="src\config.cpp" />
155 <ClCompile Include="src\crc.cpp" />
156 <ClCompile Include="src\file_utils.cpp" />
157 <ClCompile Include="src\hash.cpp" />
158 <ClCompile Include="src\log.cpp" />
159 <ClCompile Include="src\misc_utils.cpp" />
160 <ClCompile Include="src\timer.cpp" />
161 <ClCompile Include="src\x86_utils.cpp" />
162 <ClCompile Include="src\xml.cpp" />
163 </ItemGroup>
164 <ItemGroup> 144 <ItemGroup>
165 <ClInclude Include="src\atomic.h" /> 145 <ClInclude Include="src\atomic.h" />
166 <ClInclude Include="src\atomic_gcc.h" /> 146 <ClInclude Include="src\atomic_gcc.h" />
167 <ClInclude Include="src\atomic_win32.h" /> 147 <ClInclude Include="src\atomic_win32.h" />
148 <ClInclude Include="src\break_points.h" />
149 <ClInclude Include="src\chunk_file.h" />
168 <ClInclude Include="src\common.h" /> 150 <ClInclude Include="src\common.h" />
169 <ClInclude Include="src\config.h" /> 151 <ClInclude Include="src\common_funcs.h" />
170 <ClInclude Include="src\crc.h" /> 152 <ClInclude Include="src\common_paths.h" />
171 <ClInclude Include="src\file_utils.h" /> 153 <ClInclude Include="src\common_types.h" />
154 <ClInclude Include="src\console_listener.h" />
155 <ClInclude Include="src\cpu_detect.h" />
156 <ClInclude Include="src\debug_interface.h" />
157 <ClInclude Include="src\extended_trace.h" />
158 <ClInclude Include="src\fifo_queue.h" />
159 <ClInclude Include="src\file_search.h" />
160 <ClInclude Include="src\file_util.h" />
161 <ClInclude Include="src\fixed_size_queue.h" />
172 <ClInclude Include="src\hash.h" /> 162 <ClInclude Include="src\hash.h" />
173 <ClInclude Include="src\hash_container.h" /> 163 <ClInclude Include="src\linear_disk_cache.h" />
174 <ClInclude Include="src\log.h" /> 164 <ClInclude Include="src\log.h" />
175 <ClInclude Include="src\misc_utils.h" /> 165 <ClInclude Include="src\log_manager.h" />
176 <ClInclude Include="src\platform.h" /> 166 <ClInclude Include="src\math_util.h" />
167 <ClInclude Include="src\memory_util.h" />
168 <ClInclude Include="src\mem_arena.h" />
169 <ClInclude Include="src\msg_handler.h" />
170 <ClInclude Include="src\scm_rev.h" />
177 <ClInclude Include="src\std_condition_variable.h" /> 171 <ClInclude Include="src\std_condition_variable.h" />
178 <ClInclude Include="src\std_mutex.h" /> 172 <ClInclude Include="src\std_mutex.h" />
179 <ClInclude Include="src\std_thread.h" /> 173 <ClInclude Include="src\std_thread.h" />
174 <ClInclude Include="src\string_util.h" />
175 <ClInclude Include="src\thread.h" />
176 <ClInclude Include="src\thunk.h" />
180 <ClInclude Include="src\timer.h" /> 177 <ClInclude Include="src\timer.h" />
181 <ClInclude Include="src\types.h" /> 178 </ItemGroup>
182 <ClInclude Include="src\x86_utils.h" /> 179 <ItemGroup>
183 <ClInclude Include="src\xml.h" /> 180 <ClCompile Include="src\break_points.cpp" />
181 <ClCompile Include="src\console_listener.cpp" />
182 <ClCompile Include="src\extended_trace.cpp" />
183 <ClCompile Include="src\file_search.cpp" />
184 <ClCompile Include="src\file_util.cpp" />
185 <ClCompile Include="src\hash.cpp" />
186 <ClCompile Include="src\log_manager.cpp" />
187 <ClCompile Include="src\math_util.cpp" />
188 <ClCompile Include="src\memory_util.cpp" />
189 <ClCompile Include="src\mem_arena.cpp" />
190 <ClCompile Include="src\misc.cpp" />
191 <ClCompile Include="src\msg_handler.cpp" />
192 <ClCompile Include="src\string_util.cpp" />
193 <ClCompile Include="src\thread.cpp" />
194 <ClCompile Include="src\timer.cpp" />
195 <ClCompile Include="src\version.cpp" />
196 </ItemGroup>
197 <ItemGroup>
198 <None Include="CMakeLists.txt" />
184 </ItemGroup> 199 </ItemGroup>
185 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 200 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
186 <ImportGroup Label="ExtensionTargets"> 201 <ImportGroup Label="ExtensionTargets">
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters
index 9d2b5c513..ab8e5d12e 100644
--- a/src/common/common.vcxproj.filters
+++ b/src/common/common.vcxproj.filters
@@ -1,35 +1,59 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 2<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <ItemGroup> 3 <ItemGroup>
4 <ClCompile Include="src\crc.cpp" /> 4 <ClCompile Include="src\break_points.cpp" />
5 <ClCompile Include="src\log.cpp" /> 5 <ClCompile Include="src\console_listener.cpp" />
6 <ClCompile Include="src\timer.cpp" /> 6 <ClCompile Include="src\extended_trace.cpp" />
7 <ClCompile Include="src\xml.cpp" /> 7 <ClCompile Include="src\file_search.cpp" />
8 <ClCompile Include="src\config.cpp" /> 8 <ClCompile Include="src\file_util.cpp" />
9 <ClCompile Include="src\misc_utils.cpp" />
10 <ClCompile Include="src\hash.cpp" /> 9 <ClCompile Include="src\hash.cpp" />
11 <ClCompile Include="src\x86_utils.cpp" /> 10 <ClCompile Include="src\log_manager.cpp" />
12 <ClCompile Include="src\file_utils.cpp" /> 11 <ClCompile Include="src\math_util.cpp" />
12 <ClCompile Include="src\memory_util.cpp" />
13 <ClCompile Include="src\mem_arena.cpp" />
14 <ClCompile Include="src\misc.cpp" />
15 <ClCompile Include="src\msg_handler.cpp" />
16 <ClCompile Include="src\string_util.cpp" />
17 <ClCompile Include="src\thread.cpp" />
18 <ClCompile Include="src\timer.cpp" />
19 <ClCompile Include="src\version.cpp" />
13 </ItemGroup> 20 </ItemGroup>
14 <ItemGroup> 21 <ItemGroup>
15 <ClInclude Include="src\crc.h" /> 22 <ClInclude Include="src\atomic.h" />
16 <ClInclude Include="src\platform.h" /> 23 <ClInclude Include="src\break_points.h" />
24 <ClInclude Include="src\chunk_file.h" />
17 <ClInclude Include="src\common.h" /> 25 <ClInclude Include="src\common.h" />
18 <ClInclude Include="src\types.h" /> 26 <ClInclude Include="src\common_funcs.h" />
27 <ClInclude Include="src\common_paths.h" />
28 <ClInclude Include="src\common_types.h" />
29 <ClInclude Include="src\console_listener.h" />
30 <ClInclude Include="src\cpu_detect.h" />
31 <ClInclude Include="src\debug_interface.h" />
32 <ClInclude Include="src\extended_trace.h" />
33 <ClInclude Include="src\fifo_queue.h" />
34 <ClInclude Include="src\file_search.h" />
35 <ClInclude Include="src\file_util.h" />
36 <ClInclude Include="src\fixed_size_queue.h" />
37 <ClInclude Include="src\hash.h" />
38 <ClInclude Include="src\linear_disk_cache.h" />
19 <ClInclude Include="src\log.h" /> 39 <ClInclude Include="src\log.h" />
20 <ClInclude Include="src\timer.h" /> 40 <ClInclude Include="src\log_manager.h" />
21 <ClInclude Include="src\x86_utils.h" /> 41 <ClInclude Include="src\math_util.h" />
22 <ClInclude Include="src\config.h" /> 42 <ClInclude Include="src\memory_util.h" />
23 <ClInclude Include="src\xml.h" /> 43 <ClInclude Include="src\mem_arena.h" />
24 <ClInclude Include="src\misc_utils.h" /> 44 <ClInclude Include="src\msg_handler.h" />
25 <ClInclude Include="src\atomic.h" /> 45 <ClInclude Include="src\scm_rev.h" />
26 <ClInclude Include="src\atomic_win32.h" />
27 <ClInclude Include="src\atomic_gcc.h" />
28 <ClInclude Include="src\std_condition_variable.h" /> 46 <ClInclude Include="src\std_condition_variable.h" />
29 <ClInclude Include="src\std_mutex.h" /> 47 <ClInclude Include="src\std_mutex.h" />
30 <ClInclude Include="src\std_thread.h" /> 48 <ClInclude Include="src\std_thread.h" />
31 <ClInclude Include="src\hash_container.h" /> 49 <ClInclude Include="src\string_util.h" />
32 <ClInclude Include="src\hash.h" /> 50 <ClInclude Include="src\thread.h" />
33 <ClInclude Include="src\file_utils.h" /> 51 <ClInclude Include="src\thunk.h" />
52 <ClInclude Include="src\timer.h" />
53 <ClInclude Include="src\atomic_gcc.h" />
54 <ClInclude Include="src\atomic_win32.h" />
55 </ItemGroup>
56 <ItemGroup>
57 <None Include="CMakeLists.txt" />
34 </ItemGroup> 58 </ItemGroup>
35</Project> \ No newline at end of file 59</Project> \ No newline at end of file
diff --git a/src/common/src/atomic.h b/src/common/src/atomic.h
new file mode 100644
index 000000000..883bc14fb
--- /dev/null
+++ b/src/common/src/atomic.h
@@ -0,0 +1,19 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _ATOMIC_H_
6#define _ATOMIC_H_
7
8#ifdef _WIN32
9
10#include "atomic_win32.h"
11
12#else
13
14// GCC-compatible compiler assumed!
15#include "atomic_gcc.h"
16
17#endif
18
19#endif
diff --git a/src/common/src/atomic_gcc.h b/src/common/src/atomic_gcc.h
new file mode 100644
index 000000000..0f820f4fa
--- /dev/null
+++ b/src/common/src/atomic_gcc.h
@@ -0,0 +1,113 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _ATOMIC_GCC_H_
6#define _ATOMIC_GCC_H_
7
8#include "common.h"
9
10// Atomic operations are performed in a single step by the CPU. It is
11// impossible for other threads to see the operation "half-done."
12//
13// Some atomic operations can be combined with different types of memory
14// barriers called "Acquire semantics" and "Release semantics", defined below.
15//
16// Acquire semantics: Future memory accesses cannot be relocated to before the
17// operation.
18//
19// Release semantics: Past memory accesses cannot be relocated to after the
20// operation.
21//
22// These barriers affect not only the compiler, but also the CPU.
23
24namespace Common
25{
26
27inline void AtomicAdd(volatile u32& target, u32 value) {
28 __sync_add_and_fetch(&target, value);
29}
30
31inline void AtomicAnd(volatile u32& target, u32 value) {
32 __sync_and_and_fetch(&target, value);
33}
34
35inline void AtomicDecrement(volatile u32& target) {
36 __sync_add_and_fetch(&target, -1);
37}
38
39inline void AtomicIncrement(volatile u32& target) {
40 __sync_add_and_fetch(&target, 1);
41}
42
43inline u32 AtomicLoad(volatile u32& src) {
44 return src; // 32-bit reads are always atomic.
45}
46inline u32 AtomicLoadAcquire(volatile u32& src) {
47 //keep the compiler from caching any memory references
48 u32 result = src; // 32-bit reads are always atomic.
49 //__sync_synchronize(); // TODO: May not be necessary.
50 // Compiler instruction only. x86 loads always have acquire semantics.
51 __asm__ __volatile__ ( "":::"memory" );
52 return result;
53}
54
55inline void AtomicOr(volatile u32& target, u32 value) {
56 __sync_or_and_fetch(&target, value);
57}
58
59inline void AtomicStore(volatile u32& dest, u32 value) {
60 dest = value; // 32-bit writes are always atomic.
61}
62inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
63 __sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function is has acquire semantics.
64}
65
66}
67
68// Old code kept here for reference in case we need the parts with __asm__ __volatile__.
69#if 0
70LONG SyncInterlockedIncrement(LONG *Dest)
71{
72#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__))
73 return __sync_add_and_fetch(Dest, 1);
74#else
75 register int result;
76 __asm__ __volatile__("lock; xadd %0,%1"
77 : "=r" (result), "=m" (*Dest)
78 : "0" (1), "m" (*Dest)
79 : "memory");
80 return result;
81#endif
82}
83
84LONG SyncInterlockedExchangeAdd(LONG *Dest, LONG Val)
85{
86#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__))
87 return __sync_add_and_fetch(Dest, Val);
88#else
89 register int result;
90 __asm__ __volatile__("lock; xadd %0,%1"
91 : "=r" (result), "=m" (*Dest)
92 : "0" (Val), "m" (*Dest)
93 : "memory");
94 return result;
95#endif
96}
97
98LONG SyncInterlockedExchange(LONG *Dest, LONG Val)
99{
100#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__))
101 return __sync_lock_test_and_set(Dest, Val);
102#else
103 register int result;
104 __asm__ __volatile__("lock; xchg %0,%1"
105 : "=r" (result), "=m" (*Dest)
106 : "0" (Val), "m" (*Dest)
107 : "memory");
108 return result;
109#endif
110}
111#endif
112
113#endif
diff --git a/src/common/src/atomic_win32.h b/src/common/src/atomic_win32.h
new file mode 100644
index 000000000..31ee0b784
--- /dev/null
+++ b/src/common/src/atomic_win32.h
@@ -0,0 +1,72 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _ATOMIC_WIN32_H_
6#define _ATOMIC_WIN32_H_
7
8#include "common.h"
9#include <intrin.h>
10#include <Windows.h>
11
12// Atomic operations are performed in a single step by the CPU. It is
13// impossible for other threads to see the operation "half-done."
14//
15// Some atomic operations can be combined with different types of memory
16// barriers called "Acquire semantics" and "Release semantics", defined below.
17//
18// Acquire semantics: Future memory accesses cannot be relocated to before the
19// operation.
20//
21// Release semantics: Past memory accesses cannot be relocated to after the
22// operation.
23//
24// These barriers affect not only the compiler, but also the CPU.
25//
26// NOTE: Acquire and Release are not differentiated right now. They perform a
27// full memory barrier instead of a "one-way" memory barrier. The newest
28// Windows SDK has Acquire and Release versions of some Interlocked* functions.
29
30namespace Common
31{
32
33inline void AtomicAdd(volatile u32& target, u32 value) {
34 InterlockedExchangeAdd((volatile LONG*)&target, (LONG)value);
35}
36
37inline void AtomicAnd(volatile u32& target, u32 value) {
38 _InterlockedAnd((volatile LONG*)&target, (LONG)value);
39}
40
41inline void AtomicIncrement(volatile u32& target) {
42 InterlockedIncrement((volatile LONG*)&target);
43}
44
45inline void AtomicDecrement(volatile u32& target) {
46 InterlockedDecrement((volatile LONG*)&target);
47}
48
49inline u32 AtomicLoad(volatile u32& src) {
50 return src; // 32-bit reads are always atomic.
51}
52inline u32 AtomicLoadAcquire(volatile u32& src) {
53 u32 result = src; // 32-bit reads are always atomic.
54 _ReadBarrier(); // Compiler instruction only. x86 loads always have acquire semantics.
55 return result;
56}
57
58inline void AtomicOr(volatile u32& target, u32 value) {
59 _InterlockedOr((volatile LONG*)&target, (LONG)value);
60}
61
62inline void AtomicStore(volatile u32& dest, u32 value) {
63 dest = value; // 32-bit writes are always atomic.
64}
65inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
66 _WriteBarrier(); // Compiler instruction only. x86 stores always have release semantics.
67 dest = value; // 32-bit writes are always atomic.
68}
69
70}
71
72#endif
diff --git a/src/common/src/break_points.cpp b/src/common/src/break_points.cpp
new file mode 100644
index 000000000..9e5c65153
--- /dev/null
+++ b/src/common/src/break_points.cpp
@@ -0,0 +1,203 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common.h"
6#include "debug_interface.h"
7#include "break_points.h"
8
9#include <sstream>
10#include <algorithm>
11
12bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
13{
14 for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
15 if (i->iAddress == _iAddress)
16 return true;
17 return false;
18}
19
20bool BreakPoints::IsTempBreakPoint(u32 _iAddress)
21{
22 for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
23 if (i->iAddress == _iAddress && i->bTemporary)
24 return true;
25 return false;
26}
27
28BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const
29{
30 TBreakPointsStr bps;
31 for (TBreakPoints::const_iterator i = m_BreakPoints.begin();
32 i != m_BreakPoints.end(); ++i)
33 {
34 if (!i->bTemporary)
35 {
36 std::stringstream bp;
37 bp << std::hex << i->iAddress << " " << (i->bOn ? "n" : "");
38 bps.push_back(bp.str());
39 }
40 }
41
42 return bps;
43}
44
45void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
46{
47 for (TBreakPointsStr::const_iterator i = bps.begin(); i != bps.end(); ++i)
48 {
49 TBreakPoint bp;
50 std::stringstream bpstr;
51 bpstr << std::hex << *i;
52 bpstr >> bp.iAddress;
53 bp.bOn = i->find("n") != i->npos;
54 bp.bTemporary = false;
55 Add(bp);
56 }
57}
58
59void BreakPoints::Add(const TBreakPoint& bp)
60{
61 if (!IsAddressBreakPoint(bp.iAddress))
62 {
63 m_BreakPoints.push_back(bp);
64 //if (jit)
65 // jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
66 }
67}
68
69void BreakPoints::Add(u32 em_address, bool temp)
70{
71 if (!IsAddressBreakPoint(em_address)) // only add new addresses
72 {
73 TBreakPoint pt; // breakpoint settings
74 pt.bOn = true;
75 pt.bTemporary = temp;
76 pt.iAddress = em_address;
77
78 m_BreakPoints.push_back(pt);
79
80 //if (jit)
81 // jit->GetBlockCache()->InvalidateICache(em_address, 4);
82 }
83}
84
85void BreakPoints::Remove(u32 em_address)
86{
87 for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
88 {
89 if (i->iAddress == em_address)
90 {
91 m_BreakPoints.erase(i);
92 //if (jit)
93 // jit->GetBlockCache()->InvalidateICache(em_address, 4);
94 return;
95 }
96 }
97}
98
99void BreakPoints::Clear()
100{
101 //if (jit)
102 //{
103 // std::for_each(m_BreakPoints.begin(), m_BreakPoints.end(),
104 // [](const TBreakPoint& bp)
105 // {
106 // jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
107 // }
108 // );
109 //}
110
111 m_BreakPoints.clear();
112}
113
114MemChecks::TMemChecksStr MemChecks::GetStrings() const
115{
116 TMemChecksStr mcs;
117 for (TMemChecks::const_iterator i = m_MemChecks.begin();
118 i != m_MemChecks.end(); ++i)
119 {
120 std::stringstream mc;
121 mc << std::hex << i->StartAddress;
122 mc << " " << (i->bRange ? i->EndAddress : i->StartAddress) << " " <<
123 (i->bRange ? "n" : "") << (i->OnRead ? "r" : "") <<
124 (i->OnWrite ? "w" : "") << (i->Log ? "l" : "") << (i->Break ? "p" : "");
125 mcs.push_back(mc.str());
126 }
127
128 return mcs;
129}
130
131void MemChecks::AddFromStrings(const TMemChecksStr& mcs)
132{
133 for (TMemChecksStr::const_iterator i = mcs.begin(); i != mcs.end(); ++i)
134 {
135 TMemCheck mc;
136 std::stringstream mcstr;
137 mcstr << std::hex << *i;
138 mcstr >> mc.StartAddress;
139 mc.bRange = i->find("n") != i->npos;
140 mc.OnRead = i->find("r") != i->npos;
141 mc.OnWrite = i->find("w") != i->npos;
142 mc.Log = i->find("l") != i->npos;
143 mc.Break = i->find("p") != i->npos;
144 if (mc.bRange)
145 mcstr >> mc.EndAddress;
146 else
147 mc.EndAddress = mc.StartAddress;
148 Add(mc);
149 }
150}
151
152void MemChecks::Add(const TMemCheck& _rMemoryCheck)
153{
154 if (GetMemCheck(_rMemoryCheck.StartAddress) == 0)
155 m_MemChecks.push_back(_rMemoryCheck);
156}
157
158void MemChecks::Remove(u32 _Address)
159{
160 for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
161 {
162 if (i->StartAddress == _Address)
163 {
164 m_MemChecks.erase(i);
165 return;
166 }
167 }
168}
169
170TMemCheck *MemChecks::GetMemCheck(u32 address)
171{
172 for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
173 {
174 if (i->bRange)
175 {
176 if (address >= i->StartAddress && address <= i->EndAddress)
177 return &(*i);
178 }
179 else if (i->StartAddress == address)
180 return &(*i);
181 }
182
183 // none found
184 return 0;
185}
186
187void TMemCheck::Action(DebugInterface *debug_interface, u32 iValue, u32 addr,
188 bool write, int size, u32 pc)
189{
190 if ((write && OnWrite) || (!write && OnRead))
191 {
192 if (Log)
193 {
194 INFO_LOG(MEMMAP, "CHK %08x (%s) %s%i %0*x at %08x (%s)",
195 pc, debug_interface->getDescription(pc).c_str(),
196 write ? "Write" : "Read", size*8, size*2, iValue, addr,
197 debug_interface->getDescription(addr).c_str()
198 );
199 }
200 if (Break)
201 debug_interface->breakNow();
202 }
203}
diff --git a/src/common/src/break_points.h b/src/common/src/break_points.h
new file mode 100644
index 000000000..281de1004
--- /dev/null
+++ b/src/common/src/break_points.h
@@ -0,0 +1,102 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _DEBUGGER_BREAKPOINTS_H
6#define _DEBUGGER_BREAKPOINTS_H
7
8#include <vector>
9#include <string>
10
11#include "common.h"
12
13class DebugInterface;
14
15struct TBreakPoint
16{
17 u32 iAddress;
18 bool bOn;
19 bool bTemporary;
20};
21
22struct TMemCheck
23{
24 TMemCheck() {
25 numHits = 0;
26 StartAddress = EndAddress = 0;
27 bRange = OnRead = OnWrite = Log = Break = false;
28 }
29 u32 StartAddress;
30 u32 EndAddress;
31
32 bool bRange;
33
34 bool OnRead;
35 bool OnWrite;
36
37 bool Log;
38 bool Break;
39
40 u32 numHits;
41
42 void Action(DebugInterface *dbg_interface, u32 _iValue, u32 addr,
43 bool write, int size, u32 pc);
44};
45
46// Code breakpoints.
47class BreakPoints
48{
49public:
50 typedef std::vector<TBreakPoint> TBreakPoints;
51 typedef std::vector<std::string> TBreakPointsStr;
52
53 const TBreakPoints& GetBreakPoints() { return m_BreakPoints; }
54
55 TBreakPointsStr GetStrings() const;
56 void AddFromStrings(const TBreakPointsStr& bps);
57
58 // is address breakpoint
59 bool IsAddressBreakPoint(u32 _iAddress);
60 bool IsTempBreakPoint(u32 _iAddress);
61
62 // Add BreakPoint
63 void Add(u32 em_address, bool temp=false);
64 void Add(const TBreakPoint& bp);
65
66 // Remove Breakpoint
67 void Remove(u32 _iAddress);
68 void Clear();
69
70 void DeleteByAddress(u32 _Address);
71
72private:
73 TBreakPoints m_BreakPoints;
74 u32 m_iBreakOnCount;
75};
76
77
78// Memory breakpoints
79class MemChecks
80{
81public:
82 typedef std::vector<TMemCheck> TMemChecks;
83 typedef std::vector<std::string> TMemChecksStr;
84
85 TMemChecks m_MemChecks;
86
87 const TMemChecks& GetMemChecks() { return m_MemChecks; }
88
89 TMemChecksStr GetStrings() const;
90 void AddFromStrings(const TMemChecksStr& mcs);
91
92 void Add(const TMemCheck& _rMemoryCheck);
93
94 // memory breakpoint
95 TMemCheck *GetMemCheck(u32 address);
96 void Remove(u32 _Address);
97
98 void Clear() { m_MemChecks.clear(); };
99};
100
101#endif
102
diff --git a/src/common/src/chunk_file.h b/src/common/src/chunk_file.h
new file mode 100644
index 000000000..0c333b094
--- /dev/null
+++ b/src/common/src/chunk_file.h
@@ -0,0 +1,384 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _POINTERWRAP_H_
7#define _POINTERWRAP_H_
8
9// Extremely simple serialization framework.
10
11// (mis)-features:
12// + Super fast
13// + Very simple
14// + Same code is used for serialization and deserializaition (in most cases)
15// - Zero backwards/forwards compatibility
16// - Serialization code for anything complex has to be manually written.
17
18#include <map>
19#include <vector>
20#include <list>
21#include <deque>
22#include <string>
23#include <type_traits>
24
25#include "common.h"
26#include "file_util.h"
27
28template <class T>
29struct LinkedListItem : public T
30{
31 LinkedListItem<T> *next;
32};
33
34// Wrapper class
35class PointerWrap
36{
37public:
38 enum Mode
39 {
40 MODE_READ = 1, // load
41 MODE_WRITE, // save
42 MODE_MEASURE, // calculate size
43 MODE_VERIFY, // compare
44 };
45
46 u8 **ptr;
47 Mode mode;
48
49public:
50 PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {}
51
52 void SetMode(Mode mode_) { mode = mode_; }
53 Mode GetMode() const { return mode; }
54 u8** GetPPtr() { return ptr; }
55
56 template <typename K, class V>
57 void Do(std::map<K, V>& x)
58 {
59 u32 count = (u32)x.size();
60 Do(count);
61
62 switch (mode)
63 {
64 case MODE_READ:
65 for (x.clear(); count != 0; --count)
66 {
67 std::pair<K, V> pair;
68 Do(pair.first);
69 Do(pair.second);
70 x.insert(pair);
71 }
72 break;
73
74 case MODE_WRITE:
75 case MODE_MEASURE:
76 case MODE_VERIFY:
77 for (auto itr = x.begin(); itr != x.end(); ++itr)
78 {
79 Do(itr->first);
80 Do(itr->second);
81 }
82 break;
83 }
84 }
85
86 template <typename T>
87 void DoContainer(T& x)
88 {
89 u32 size = (u32)x.size();
90 Do(size);
91 x.resize(size);
92
93 for (auto itr = x.begin(); itr != x.end(); ++itr)
94 Do(*itr);
95 }
96
97 template <typename T>
98 void Do(std::vector<T>& x)
99 {
100 DoContainer(x);
101 }
102
103 template <typename T>
104 void Do(std::list<T>& x)
105 {
106 DoContainer(x);
107 }
108
109 template <typename T>
110 void Do(std::deque<T>& x)
111 {
112 DoContainer(x);
113 }
114
115 template <typename T>
116 void Do(std::basic_string<T>& x)
117 {
118 DoContainer(x);
119 }
120
121 template <typename T>
122 void DoArray(T* x, u32 count)
123 {
124 for (u32 i = 0; i != count; ++i)
125 Do(x[i]);
126 }
127
128 template <typename T>
129 void Do(T& x)
130 {
131 // Ideally this would be std::is_trivially_copyable, but not enough support yet
132 static_assert(std::is_pod<T>::value, "Only sane for POD types");
133
134 DoVoid((void*)&x, sizeof(x));
135 }
136
137 template <typename T>
138 void DoPOD(T& x)
139 {
140 DoVoid((void*)&x, sizeof(x));
141 }
142
143 template <typename T>
144 void DoPointer(T*& x, T* const base)
145 {
146 // pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range
147 s32 offset = x - base;
148 Do(offset);
149 if (mode == MODE_READ)
150 x = base + offset;
151 }
152
153 // Let's pretend std::list doesn't exist!
154 template <class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*), void (*TDo)(PointerWrap&, T*)>
155 void DoLinkedList(LinkedListItem<T>*& list_start, LinkedListItem<T>** list_end=0)
156 {
157 LinkedListItem<T>* list_cur = list_start;
158 LinkedListItem<T>* prev = 0;
159
160 while (true)
161 {
162 u8 shouldExist = (list_cur ? 1 : 0);
163 Do(shouldExist);
164 if (shouldExist == 1)
165 {
166 LinkedListItem<T>* cur = list_cur ? list_cur : TNew();
167 TDo(*this, (T*)cur);
168 if (!list_cur)
169 {
170 if (mode == MODE_READ)
171 {
172 cur->next = 0;
173 list_cur = cur;
174 if (prev)
175 prev->next = cur;
176 else
177 list_start = cur;
178 }
179 else
180 {
181 TFree(cur);
182 continue;
183 }
184 }
185 }
186 else
187 {
188 if (mode == MODE_READ)
189 {
190 if (prev)
191 prev->next = 0;
192 if (list_end)
193 *list_end = prev;
194 if (list_cur)
195 {
196 if (list_start == list_cur)
197 list_start = 0;
198 do
199 {
200 LinkedListItem<T>* next = list_cur->next;
201 TFree(list_cur);
202 list_cur = next;
203 }
204 while (list_cur);
205 }
206 }
207 break;
208 }
209 prev = list_cur;
210 list_cur = list_cur->next;
211 }
212 }
213
214 void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42)
215 {
216 u32 cookie = arbitraryNumber;
217 Do(cookie);
218
219 if (mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
220 {
221 PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...",
222 prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
223 mode = PointerWrap::MODE_MEASURE;
224 }
225 }
226
227private:
228 __forceinline void DoByte(u8& x)
229 {
230 switch (mode)
231 {
232 case MODE_READ:
233 x = **ptr;
234 break;
235
236 case MODE_WRITE:
237 **ptr = x;
238 break;
239
240 case MODE_MEASURE:
241 break;
242
243 case MODE_VERIFY:
244 _dbg_assert_msg_(COMMON, (x == **ptr),
245 "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
246 x, x, &x, **ptr, **ptr, *ptr);
247 break;
248
249 default:
250 break;
251 }
252
253 ++(*ptr);
254 }
255
256 void DoVoid(void *data, u32 size)
257 {
258 for(u32 i = 0; i != size; ++i)
259 DoByte(reinterpret_cast<u8*>(data)[i]);
260 }
261};
262
263class CChunkFileReader
264{
265public:
266 // Load file template
267 template<class T>
268 static bool Load(const std::string& _rFilename, u32 _Revision, T& _class)
269 {
270 INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str());
271
272 if (!File::Exists(_rFilename))
273 return false;
274
275 // Check file size
276 const u64 fileSize = File::GetSize(_rFilename);
277 static const u64 headerSize = sizeof(SChunkHeader);
278 if (fileSize < headerSize)
279 {
280 ERROR_LOG(COMMON,"ChunkReader: File too small");
281 return false;
282 }
283
284 File::IOFile pFile(_rFilename, "rb");
285 if (!pFile)
286 {
287 ERROR_LOG(COMMON,"ChunkReader: Can't open file for reading");
288 return false;
289 }
290
291 // read the header
292 SChunkHeader header;
293 if (!pFile.ReadArray(&header, 1))
294 {
295 ERROR_LOG(COMMON,"ChunkReader: Bad header size");
296 return false;
297 }
298
299 // Check revision
300 if (header.Revision != _Revision)
301 {
302 ERROR_LOG(COMMON,"ChunkReader: Wrong file revision, got %d expected %d",
303 header.Revision, _Revision);
304 return false;
305 }
306
307 // get size
308 const u32 sz = (u32)(fileSize - headerSize);
309 if (header.ExpectedSize != sz)
310 {
311 ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
312 sz, header.ExpectedSize);
313 return false;
314 }
315
316 // read the state
317 std::vector<u8> buffer(sz);
318 if (!pFile.ReadArray(&buffer[0], sz))
319 {
320 ERROR_LOG(COMMON,"ChunkReader: Error reading file");
321 return false;
322 }
323
324 u8* ptr = &buffer[0];
325 PointerWrap p(&ptr, PointerWrap::MODE_READ);
326 _class.DoState(p);
327
328 INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str());
329 return true;
330 }
331
332 // Save file template
333 template<class T>
334 static bool Save(const std::string& _rFilename, u32 _Revision, T& _class)
335 {
336 INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
337 File::IOFile pFile(_rFilename, "wb");
338 if (!pFile)
339 {
340 ERROR_LOG(COMMON,"ChunkReader: Error opening file for write");
341 return false;
342 }
343
344 // Get data
345 u8 *ptr = 0;
346 PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
347 _class.DoState(p);
348 size_t const sz = (size_t)ptr;
349 std::vector<u8> buffer(sz);
350 ptr = &buffer[0];
351 p.SetMode(PointerWrap::MODE_WRITE);
352 _class.DoState(p);
353
354 // Create header
355 SChunkHeader header;
356 header.Revision = _Revision;
357 header.ExpectedSize = (u32)sz;
358
359 // Write to file
360 if (!pFile.WriteArray(&header, 1))
361 {
362 ERROR_LOG(COMMON,"ChunkReader: Failed writing header");
363 return false;
364 }
365
366 if (!pFile.WriteArray(&buffer[0], sz))
367 {
368 ERROR_LOG(COMMON,"ChunkReader: Failed writing data");
369 return false;
370 }
371
372 INFO_LOG(COMMON,"ChunkReader: Done writing %s", _rFilename.c_str());
373 return true;
374 }
375
376private:
377 struct SChunkHeader
378 {
379 u32 Revision;
380 u32 ExpectedSize;
381 };
382};
383
384#endif // _POINTERWRAP_H_
diff --git a/src/common/src/common.h b/src/common/src/common.h
new file mode 100644
index 000000000..f95d58074
--- /dev/null
+++ b/src/common/src/common.h
@@ -0,0 +1,164 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _COMMON_H_
6#define _COMMON_H_
7
8// DO NOT EVER INCLUDE <windows.h> directly _or indirectly_ from this file
9// since it slows down the build a lot.
10
11#include <stdlib.h>
12#include <stdio.h>
13#include <string.h>
14
15// SVN version number
16extern const char *scm_rev_str;
17extern const char *netplay_dolphin_ver;
18
19// Force enable logging in the right modes. For some reason, something had changed
20// so that debugfast no longer logged.
21#if defined(_DEBUG) || defined(DEBUGFAST)
22#undef LOGGING
23#define LOGGING 1
24#endif
25
26#define STACKALIGN
27
28#if __cplusplus >= 201103 || defined(_MSC_VER) || defined(__GXX_EXPERIMENTAL_CXX0X__)
29#define HAVE_CXX11_SYNTAX 1
30#endif
31
32#if HAVE_CXX11_SYNTAX
33// An inheritable class to disallow the copy constructor and operator= functions
34class NonCopyable
35{
36protected:
37 NonCopyable() {}
38 NonCopyable(const NonCopyable&&) {}
39 void operator=(const NonCopyable&&) {}
40private:
41 NonCopyable(NonCopyable&);
42 NonCopyable& operator=(NonCopyable& other);
43};
44#endif
45
46#include "log.h"
47#include "common_types.h"
48#include "msg_handler.h"
49#include "common_funcs.h"
50
51#ifdef __APPLE__
52// The Darwin ABI requires that stack frames be aligned to 16-byte boundaries.
53// This is only needed on i386 gcc - x86_64 already aligns to 16 bytes.
54#if defined __i386__ && defined __GNUC__
55#undef STACKALIGN
56#define STACKALIGN __attribute__((__force_align_arg_pointer__))
57#endif
58
59#elif defined _WIN32
60
61// Check MSC ver
62 #if !defined _MSC_VER || _MSC_VER <= 1000
63 #error needs at least version 1000 of MSC
64 #endif
65
66 #define NOMINMAX
67
68// Memory leak checks
69 #define CHECK_HEAP_INTEGRITY()
70
71// Alignment
72 #define GC_ALIGNED16(x) __declspec(align(16)) x
73 #define GC_ALIGNED32(x) __declspec(align(32)) x
74 #define GC_ALIGNED64(x) __declspec(align(64)) x
75 #define GC_ALIGNED128(x) __declspec(align(128)) x
76 #define GC_ALIGNED16_DECL(x) __declspec(align(16)) x
77 #define GC_ALIGNED64_DECL(x) __declspec(align(64)) x
78
79// Since they are always around on windows
80 #define HAVE_WX 1
81 #define HAVE_OPENAL 1
82
83 #define HAVE_PORTAUDIO 1
84
85// Debug definitions
86 #if defined(_DEBUG)
87 #include <crtdbg.h>
88 #undef CHECK_HEAP_INTEGRITY
89 #define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");}
90 // If you want to see how much a pain in the ass singletons are, for example:
91 // {614} normal block at 0x030C5310, 188 bytes long.
92 // Data: <Master Log > 4D 61 73 74 65 72 20 4C 6F 67 00 00 00 00 00 00
93 struct CrtDebugBreak { CrtDebugBreak(int spot) { _CrtSetBreakAlloc(spot); } };
94 //CrtDebugBreak breakAt(614);
95 #endif // end DEBUG/FAST
96
97#endif
98
99// Windows compatibility
100#ifndef _WIN32
101#include <limits.h>
102#define MAX_PATH PATH_MAX
103#ifdef _LP64
104#define _M_X64 1
105#else
106#define _M_IX86 1
107#endif
108#define __forceinline inline __attribute__((always_inline))
109#define GC_ALIGNED16(x) __attribute__((aligned(16))) x
110#define GC_ALIGNED32(x) __attribute__((aligned(32))) x
111#define GC_ALIGNED64(x) __attribute__((aligned(64))) x
112#define GC_ALIGNED128(x) __attribute__((aligned(128))) x
113#define GC_ALIGNED16_DECL(x) __attribute__((aligned(16))) x
114#define GC_ALIGNED64_DECL(x) __attribute__((aligned(64))) x
115#endif
116
117#ifdef _MSC_VER
118#define __strdup _strdup
119#define __getcwd _getcwd
120#define __chdir _chdir
121#else
122#define __strdup strdup
123#define __getcwd getcwd
124#define __chdir chdir
125#endif
126
127// Dummy macro for marking translatable strings that can not be immediately translated.
128// wxWidgets does not have a true dummy macro for this.
129#define _trans(a) a
130
131#if defined _M_GENERIC
132# define _M_SSE 0x0
133#elif defined __GNUC__
134# if defined __SSE4_2__
135# define _M_SSE 0x402
136# elif defined __SSE4_1__
137# define _M_SSE 0x401
138# elif defined __SSSE3__
139# define _M_SSE 0x301
140# elif defined __SSE3__
141# define _M_SSE 0x300
142# endif
143#elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008
144# define _M_SSE 0x402
145#endif
146
147// Host communication.
148enum HOST_COMM
149{
150 // Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on
151 WM_USER_STOP = 10,
152 WM_USER_CREATE,
153 WM_USER_SETCURSOR,
154};
155
156// Used for notification on emulation state
157enum EMUSTATE_CHANGE
158{
159 EMUSTATE_CHANGE_PLAY = 1,
160 EMUSTATE_CHANGE_PAUSE,
161 EMUSTATE_CHANGE_STOP
162};
163
164#endif // _COMMON_H_
diff --git a/src/common/src/common_funcs.h b/src/common/src/common_funcs.h
new file mode 100644
index 000000000..73320a3ac
--- /dev/null
+++ b/src/common/src/common_funcs.h
@@ -0,0 +1,243 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _COMMONFUNCS_H_
6#define _COMMONFUNCS_H_
7
8#ifdef _WIN32
9#define SLEEP(x) Sleep(x)
10#else
11#include <unistd.h>
12#define SLEEP(x) usleep(x*1000)
13#endif
14
15template <bool> struct CompileTimeAssert;
16template<> struct CompileTimeAssert<true> {};
17
18#define b2(x) ( (x) | ( (x) >> 1) )
19#define b4(x) ( b2(x) | ( b2(x) >> 2) )
20#define b8(x) ( b4(x) | ( b4(x) >> 4) )
21#define b16(x) ( b8(x) | ( b8(x) >> 8) )
22#define b32(x) (b16(x) | (b16(x) >>16) )
23#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
24
25#if defined __GNUC__ && !defined __SSSE3__ && !defined _M_GENERIC
26#include <emmintrin.h>
27static __inline __m128i __attribute__((__always_inline__))
28_mm_shuffle_epi8(__m128i a, __m128i mask)
29{
30 __m128i result;
31 __asm__("pshufb %1, %0"
32 : "=x" (result)
33 : "xm" (mask), "0" (a));
34 return result;
35}
36#endif
37
38#ifndef _WIN32
39
40#include <errno.h>
41#ifdef __linux__
42#include <byteswap.h>
43#elif defined __FreeBSD__
44#include <sys/endian.h>
45#endif
46
47// go to debugger mode
48 #ifdef GEKKO
49 #define Crash()
50 #elif defined _M_GENERIC
51 #define Crash() { exit(1); }
52 #else
53 #define Crash() {asm ("int $3");}
54 #endif
55 #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
56// GCC 4.8 defines all the rotate functions now
57// Small issue with GCC's lrotl/lrotr intrinsics is they are still 32bit while we require 64bit
58#ifndef _rotl
59inline u32 _rotl(u32 x, int shift) {
60 shift &= 31;
61 if (!shift) return x;
62 return (x << shift) | (x >> (32 - shift));
63}
64
65inline u32 _rotr(u32 x, int shift) {
66 shift &= 31;
67 if (!shift) return x;
68 return (x >> shift) | (x << (32 - shift));
69}
70#endif
71
72inline u64 _rotl64(u64 x, unsigned int shift){
73 unsigned int n = shift % 64;
74 return (x << n) | (x >> (64 - n));
75}
76
77inline u64 _rotr64(u64 x, unsigned int shift){
78 unsigned int n = shift % 64;
79 return (x >> n) | (x << (64 - n));
80}
81
82#else // WIN32
83// Function Cross-Compatibility
84 #define strcasecmp _stricmp
85 #define strncasecmp _strnicmp
86 #define unlink _unlink
87 #define snprintf _snprintf
88 #define vscprintf _vscprintf
89
90// Locale Cross-Compatibility
91 #define locale_t _locale_t
92 #define freelocale _free_locale
93 #define newlocale(mask, locale, base) _create_locale(mask, locale)
94
95 #define LC_GLOBAL_LOCALE ((locale_t)-1)
96 #define LC_ALL_MASK LC_ALL
97 #define LC_COLLATE_MASK LC_COLLATE
98 #define LC_CTYPE_MASK LC_CTYPE
99 #define LC_MONETARY_MASK LC_MONETARY
100 #define LC_NUMERIC_MASK LC_NUMERIC
101 #define LC_TIME_MASK LC_TIME
102
103 inline locale_t uselocale(locale_t new_locale)
104 {
105 // Retrieve the current per thread locale setting
106 bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE);
107
108 // Retrieve the current thread-specific locale
109 locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE;
110
111 if(new_locale == LC_GLOBAL_LOCALE)
112 {
113 // Restore the global locale
114 _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
115 }
116 else if(new_locale != NULL)
117 {
118 // Configure the thread to set the locale only for this thread
119 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
120
121 // Set all locale categories
122 for(int i = LC_MIN; i <= LC_MAX; i++)
123 setlocale(i, new_locale->locinfo->lc_category[i].locale);
124 }
125
126 return old_locale;
127 }
128
129// 64 bit offsets for windows
130 #define fseeko _fseeki64
131 #define ftello _ftelli64
132 #define atoll _atoi64
133 #define stat64 _stat64
134 #define fstat64 _fstat64
135 #define fileno _fileno
136
137 #if _M_IX86
138 #define Crash() {__asm int 3}
139 #else
140extern "C" {
141 __declspec(dllimport) void __stdcall DebugBreak(void);
142}
143 #define Crash() {DebugBreak();}
144 #endif // M_IX86
145#endif // WIN32 ndef
146
147// Dolphin's min and max functions
148#undef min
149#undef max
150
151template<class T>
152inline T min(const T& a, const T& b) {return a > b ? b : a;}
153template<class T>
154inline T max(const T& a, const T& b) {return a > b ? a : b;}
155
156// Generic function to get last error message.
157// Call directly after the command or use the error num.
158// This function might change the error code.
159// Defined in Misc.cpp.
160const char* GetLastErrorMsg();
161
162namespace Common
163{
164inline u8 swap8(u8 _data) {return _data;}
165inline u32 swap24(const u8* _data) {return (_data[0] << 16) | (_data[1] << 8) | _data[2];}
166
167#ifdef ANDROID
168#undef swap16
169#undef swap32
170#undef swap64
171#endif
172
173#ifdef _WIN32
174inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);}
175inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);}
176inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);}
177#elif _M_ARM
178inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;}
179inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;}
180inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);}
181#elif __linux__
182inline u16 swap16(u16 _data) {return bswap_16(_data);}
183inline u32 swap32(u32 _data) {return bswap_32(_data);}
184inline u64 swap64(u64 _data) {return bswap_64(_data);}
185#elif __APPLE__
186inline __attribute__((always_inline)) u16 swap16(u16 _data)
187 {return (_data >> 8) | (_data << 8);}
188inline __attribute__((always_inline)) u32 swap32(u32 _data)
189 {return __builtin_bswap32(_data);}
190inline __attribute__((always_inline)) u64 swap64(u64 _data)
191 {return __builtin_bswap64(_data);}
192#elif __FreeBSD__
193inline u16 swap16(u16 _data) {return bswap16(_data);}
194inline u32 swap32(u32 _data) {return bswap32(_data);}
195inline u64 swap64(u64 _data) {return bswap64(_data);}
196#else
197// Slow generic implementation.
198inline u16 swap16(u16 data) {return (data >> 8) | (data << 8);}
199inline u32 swap32(u32 data) {return (swap16(data) << 16) | swap16(data >> 16);}
200inline u64 swap64(u64 data) {return ((u64)swap32(data) << 32) | swap32(data >> 32);}
201#endif
202
203inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);}
204inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);}
205inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);}
206
207template <int count>
208void swap(u8*);
209
210template <>
211inline void swap<1>(u8* data)
212{}
213
214template <>
215inline void swap<2>(u8* data)
216{
217 *reinterpret_cast<u16*>(data) = swap16(data);
218}
219
220template <>
221inline void swap<4>(u8* data)
222{
223 *reinterpret_cast<u32*>(data) = swap32(data);
224}
225
226template <>
227inline void swap<8>(u8* data)
228{
229 *reinterpret_cast<u64*>(data) = swap64(data);
230}
231
232template <typename T>
233inline T FromBigEndian(T data)
234{
235 //static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
236
237 swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
238 return data;
239}
240
241} // Namespace Common
242
243#endif // _COMMONFUNCS_H_
diff --git a/src/common/src/common_paths.h b/src/common/src/common_paths.h
new file mode 100644
index 000000000..9af93ab74
--- /dev/null
+++ b/src/common/src/common_paths.h
@@ -0,0 +1,71 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _COMMON_PATHS_H_
6#define _COMMON_PATHS_H_
7
8// Make sure we pick up USER_DIR if set in config.h
9#include "common.h"
10
11// Directory seperators, do we need this?
12#define DIR_SEP "/"
13#define DIR_SEP_CHR '/'
14
15// The user data dir
16#define ROOT_DIR "."
17#ifdef _WIN32
18 #define USERDATA_DIR "user"
19 #define DOLPHIN_DATA_DIR "akiru"
20#else
21 #define USERDATA_DIR "user"
22 #ifdef USER_DIR
23 #define DOLPHIN_DATA_DIR USER_DIR
24 #else
25 #define DOLPHIN_DATA_DIR ".akiru"
26 #endif
27#endif
28
29// Shared data dirs (Sys and shared User for linux)
30#ifdef _WIN32
31 #define SYSDATA_DIR "sys"
32#else
33 #ifdef DATA_DIR
34 #define SYSDATA_DIR DATA_DIR "sys"
35 #define SHARED_USER_DIR DATA_DIR USERDATA_DIR DIR_SEP
36 #else
37 #define SYSDATA_DIR "sys"
38 #define SHARED_USER_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP
39 #endif
40#endif
41
42// Dirs in both User and Sys
43#define EUR_DIR "EUR"
44#define USA_DIR "USA"
45#define JAP_DIR "JAP"
46
47// Subdirs in the User dir returned by GetUserPath(D_USER_IDX)
48#define CONFIG_DIR "config"
49#define GAMECONFIG_DIR "game_config"
50#define MAPS_DIR "maps"
51#define CACHE_DIR "cache"
52#define SHADERCACHE_DIR "shader_cache"
53#define STATESAVES_DIR "state_saves"
54#define SCREENSHOTS_DIR "screenShots"
55#define DUMP_DIR "dump"
56#define DUMP_TEXTURES_DIR "textures"
57#define DUMP_FRAMES_DIR "frames"
58#define DUMP_AUDIO_DIR "audio"
59#define LOGS_DIR "logs"
60#define SHADERS_DIR "shaders"
61
62// Filenames
63// Files in the directory returned by GetUserPath(D_CONFIG_IDX)
64#define AKIRU_CONFIG "akiru.ini"
65#define DEBUGGER_CONFIG "debugger.ini"
66#define LOGGER_CONFIG "logger.ini"
67
68// Files in the directory returned by GetUserPath(D_LOGS_IDX)
69#define MAIN_LOG "akiru.log"
70
71#endif // _COMMON_PATHS_H_
diff --git a/src/common/src/common_types.h b/src/common/src/common_types.h
new file mode 100644
index 000000000..5cb402131
--- /dev/null
+++ b/src/common/src/common_types.h
@@ -0,0 +1,48 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6// This header contains type definitions that are shared between the Dolphin core and
7// other parts of the code. Any definitions that are only used by the core should be
8// placed in "common.h" instead.
9
10#ifndef _COMMONTYPES_H_
11#define _COMMONTYPES_H_
12
13#ifdef _WIN32
14
15#include <tchar.h>
16
17typedef unsigned __int8 u8;
18typedef unsigned __int16 u16;
19typedef unsigned __int32 u32;
20typedef unsigned __int64 u64;
21
22typedef signed __int8 s8;
23typedef signed __int16 s16;
24typedef signed __int32 s32;
25typedef signed __int64 s64;
26
27#else
28
29#ifndef GEKKO
30
31typedef unsigned char u8;
32typedef unsigned short u16;
33typedef unsigned int u32;
34typedef unsigned long long u64;
35
36typedef signed char s8;
37typedef signed short s16;
38typedef signed int s32;
39typedef signed long long s64;
40
41#endif
42// For using windows lock code
43#define TCHAR char
44#define LONG int
45
46#endif // _WIN32
47
48#endif // _COMMONTYPES_H_
diff --git a/src/common/src/console_listener.cpp b/src/common/src/console_listener.cpp
new file mode 100644
index 000000000..84f57675d
--- /dev/null
+++ b/src/common/src/console_listener.cpp
@@ -0,0 +1,337 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <algorithm> // min
6#include <string> // System: To be able to add strings with "+"
7#include <stdio.h>
8#include <math.h>
9#ifdef _WIN32
10#include <windows.h>
11#include <array>
12#else
13#include <stdarg.h>
14#endif
15
16#include "common.h"
17#include "log_manager.h" // Common
18#include "console_listener.h" // Common
19
20ConsoleListener::ConsoleListener()
21{
22#ifdef _WIN32
23 hConsole = NULL;
24 bUseColor = true;
25#else
26 bUseColor = isatty(fileno(stdout));
27#endif
28}
29
30ConsoleListener::~ConsoleListener()
31{
32 Close();
33}
34
35// 100, 100, "Dolphin Log Console"
36// Open console window - width and height is the size of console window
37// Name is the window title
38void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title)
39{
40#ifdef _WIN32
41 if (!GetConsoleWindow())
42 {
43 // Open the console window and create the window handle for GetStdHandle()
44 AllocConsole();
45 // Hide
46 if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE);
47 // Save the window handle that AllocConsole() created
48 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
49 // Set the console window title
50 SetConsoleTitle(UTF8ToTStr(Title).c_str());
51 // Set letter space
52 LetterSpace(80, 4000);
53 //MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
54 }
55 else
56 {
57 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
58 }
59#endif
60}
61
62void ConsoleListener::UpdateHandle()
63{
64#ifdef _WIN32
65 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
66#endif
67}
68
69// Close the console window and close the eventual file handle
70void ConsoleListener::Close()
71{
72#ifdef _WIN32
73 if (hConsole == NULL)
74 return;
75 FreeConsole();
76 hConsole = NULL;
77#else
78 fflush(NULL);
79#endif
80}
81
82bool ConsoleListener::IsOpen()
83{
84#ifdef _WIN32
85 return (hConsole != NULL);
86#else
87 return true;
88#endif
89}
90
91/*
92 LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are
93 dependent on each other, that's the reason for the additional checks.
94*/
95void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst)
96{
97#ifdef _WIN32
98 BOOL SB, SW;
99 if (BufferFirst)
100 {
101 // Change screen buffer size
102 COORD Co = {BufferWidth, BufferHeight};
103 SB = SetConsoleScreenBufferSize(hConsole, Co);
104 // Change the screen buffer window size
105 SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom
106 SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
107 }
108 else
109 {
110 // Change the screen buffer window size
111 SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom
112 SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
113 // Change screen buffer size
114 COORD Co = {BufferWidth, BufferHeight};
115 SB = SetConsoleScreenBufferSize(hConsole, Co);
116 }
117#endif
118}
119void ConsoleListener::LetterSpace(int Width, int Height)
120{
121#ifdef _WIN32
122 // Get console info
123 CONSOLE_SCREEN_BUFFER_INFO ConInfo;
124 GetConsoleScreenBufferInfo(hConsole, &ConInfo);
125
126 //
127 int OldBufferWidth = ConInfo.dwSize.X;
128 int OldBufferHeight = ConInfo.dwSize.Y;
129 int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left);
130 int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top);
131 //
132 int NewBufferWidth = Width;
133 int NewBufferHeight = Height;
134 int NewScreenWidth = NewBufferWidth - 1;
135 int NewScreenHeight = OldScreenHeight;
136
137 // Width
138 BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1));
139 // Height
140 BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1));
141
142 // Resize the window too
143 //MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true);
144#endif
145}
146#ifdef _WIN32
147COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
148{
149 COORD Ret = {0, 0};
150 // Full rows
151 int Step = (int)floor((float)BytesRead / (float)BufferWidth);
152 Ret.Y += Step;
153 // Partial row
154 Ret.X = BytesRead - (BufferWidth * Step);
155 return Ret;
156}
157#endif
158void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize)
159{
160#ifdef _WIN32
161 // Check size
162 if (Width < 8 || Height < 12) return;
163
164 bool DBef = true;
165 bool DAft = true;
166 std::string SLog = "";
167
168 const HWND hWnd = GetConsoleWindow();
169 const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
170
171 // Get console info
172 CONSOLE_SCREEN_BUFFER_INFO ConInfo;
173 GetConsoleScreenBufferInfo(hConsole, &ConInfo);
174 DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y;
175
176 // ---------------------------------------------------------------------
177 // Save the current text
178 // ------------------------
179 DWORD cCharsRead = 0;
180 COORD coordScreen = { 0, 0 };
181
182 static const int MAX_BYTES = 1024 * 16;
183
184 std::vector<std::array<TCHAR, MAX_BYTES>> Str;
185 std::vector<std::array<WORD, MAX_BYTES>> Attr;
186
187 // ReadConsoleOutputAttribute seems to have a limit at this level
188 static const int ReadBufferSize = MAX_BYTES - 32;
189
190 DWORD cAttrRead = ReadBufferSize;
191 DWORD BytesRead = 0;
192 while (BytesRead < BufferSize)
193 {
194 Str.resize(Str.size() + 1);
195 if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead))
196 SLog += StringFromFormat("WriteConsoleOutputCharacter error");
197
198 Attr.resize(Attr.size() + 1);
199 if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead))
200 SLog += StringFromFormat("WriteConsoleOutputAttribute error");
201
202 // Break on error
203 if (cAttrRead == 0) break;
204 BytesRead += cAttrRead;
205 coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X);
206 }
207 // Letter space
208 int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f);
209 int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f);
210 int LBufWidth = LWidth + 1;
211 int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth);
212 // Change screen buffer size
213 LetterSpace(LBufWidth, LBufHeight);
214
215
216 ClearScreen(true);
217 coordScreen.Y = 0;
218 coordScreen.X = 0;
219 DWORD cCharsWritten = 0;
220
221 int BytesWritten = 0;
222 DWORD cAttrWritten = 0;
223 for (size_t i = 0; i < Attr.size(); i++)
224 {
225 if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten))
226 SLog += StringFromFormat("WriteConsoleOutputCharacter error");
227 if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten))
228 SLog += StringFromFormat("WriteConsoleOutputAttribute error");
229
230 BytesWritten += cAttrWritten;
231 coordScreen = GetCoordinates(BytesWritten, LBufWidth);
232 }
233
234 const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X;
235 COORD Coo = GetCoordinates(OldCursor, LBufWidth);
236 SetConsoleCursorPosition(hConsole, Coo);
237
238 if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str());
239
240 // Resize the window too
241 if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true);
242#endif
243}
244
245void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
246{
247#if defined(_WIN32)
248 /*
249 const int MAX_BYTES = 1024*10;
250 char Str[MAX_BYTES];
251 va_list ArgPtr;
252 int Cnt;
253 va_start(ArgPtr, Text);
254 Cnt = vsnprintf(Str, MAX_BYTES, Text, ArgPtr);
255 va_end(ArgPtr);
256 */
257 DWORD cCharsWritten;
258 WORD Color;
259
260 switch (Level)
261 {
262 case NOTICE_LEVEL: // light green
263 Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
264 break;
265 case ERROR_LEVEL: // light red
266 Color = FOREGROUND_RED | FOREGROUND_INTENSITY;
267 break;
268 case WARNING_LEVEL: // light yellow
269 Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
270 break;
271 case INFO_LEVEL: // cyan
272 Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
273 break;
274 case DEBUG_LEVEL: // gray
275 Color = FOREGROUND_INTENSITY;
276 break;
277 default: // off-white
278 Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
279 break;
280 }
281 if (strlen(Text) > 10)
282 {
283 // First 10 chars white
284 SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
285 WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL);
286 Text += 10;
287 }
288 SetConsoleTextAttribute(hConsole, Color);
289 WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL);
290#else
291 char ColorAttr[16] = "";
292 char ResetAttr[16] = "";
293
294 if (bUseColor)
295 {
296 strcpy(ResetAttr, "\033[0m");
297 switch (Level)
298 {
299 case NOTICE_LEVEL: // light green
300 strcpy(ColorAttr, "\033[92m");
301 break;
302 case ERROR_LEVEL: // light red
303 strcpy(ColorAttr, "\033[91m");
304 break;
305 case WARNING_LEVEL: // light yellow
306 strcpy(ColorAttr, "\033[93m");
307 break;
308 default:
309 break;
310 }
311 }
312 fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr);
313#endif
314}
315// Clear console screen
316void ConsoleListener::ClearScreen(bool Cursor)
317{
318#if defined(_WIN32)
319 COORD coordScreen = { 0, 0 };
320 DWORD cCharsWritten;
321 CONSOLE_SCREEN_BUFFER_INFO csbi;
322 DWORD dwConSize;
323
324 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
325
326 GetConsoleScreenBufferInfo(hConsole, &csbi);
327 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
328 // Write space to the entire console
329 FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
330 GetConsoleScreenBufferInfo(hConsole, &csbi);
331 FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
332 // Reset cursor
333 if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
334#endif
335}
336
337
diff --git a/src/common/src/console_listener.h b/src/common/src/console_listener.h
new file mode 100644
index 000000000..ab5c00980
--- /dev/null
+++ b/src/common/src/console_listener.h
@@ -0,0 +1,41 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _CONSOLELISTENER_H
6#define _CONSOLELISTENER_H
7
8#include "log_manager.h"
9
10#ifdef _WIN32
11#include <windows.h>
12#endif
13
14class ConsoleListener : public LogListener
15{
16public:
17 ConsoleListener();
18 ~ConsoleListener();
19
20 void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console");
21 void UpdateHandle();
22 void Close();
23 bool IsOpen();
24 void LetterSpace(int Width, int Height);
25 void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst);
26 void PixelSpace(int Left, int Top, int Width, int Height, bool);
27#ifdef _WIN32
28 COORD GetCoordinates(int BytesRead, int BufferWidth);
29#endif
30 void Log(LogTypes::LOG_LEVELS, const char *Text);
31 void ClearScreen(bool Cursor = true);
32
33private:
34#ifdef _WIN32
35 HWND GetHwnd(void);
36 HANDLE hConsole;
37#endif
38 bool bUseColor;
39};
40
41#endif // _CONSOLELISTENER_H
diff --git a/src/common/src/cpu_detect.h b/src/common/src/cpu_detect.h
new file mode 100644
index 000000000..be6ce3498
--- /dev/null
+++ b/src/common/src/cpu_detect.h
@@ -0,0 +1,81 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6// Detect the cpu, so we'll know which optimizations to use
7#ifndef _CPUDETECT_H_
8#define _CPUDETECT_H_
9
10#include <string>
11
12enum CPUVendor
13{
14 VENDOR_INTEL = 0,
15 VENDOR_AMD = 1,
16 VENDOR_ARM = 2,
17 VENDOR_OTHER = 3,
18};
19
20struct CPUInfo
21{
22 CPUVendor vendor;
23
24 char cpu_string[0x21];
25 char brand_string[0x41];
26 bool OS64bit;
27 bool CPU64bit;
28 bool Mode64bit;
29
30 bool HTT;
31 int num_cores;
32 int logical_cpu_count;
33
34 bool bSSE;
35 bool bSSE2;
36 bool bSSE3;
37 bool bSSSE3;
38 bool bPOPCNT;
39 bool bSSE4_1;
40 bool bSSE4_2;
41 bool bLZCNT;
42 bool bSSE4A;
43 bool bAVX;
44 bool bAES;
45 bool bLAHFSAHF64;
46 bool bLongMode;
47
48 // ARM specific CPUInfo
49 bool bSwp;
50 bool bHalf;
51 bool bThumb;
52 bool bFastMult;
53 bool bVFP;
54 bool bEDSP;
55 bool bThumbEE;
56 bool bNEON;
57 bool bVFPv3;
58 bool bTLS;
59 bool bVFPv4;
60 bool bIDIVa;
61 bool bIDIVt;
62 bool bArmV7; // enable MOVT, MOVW etc
63
64 // ARMv8 specific
65 bool bFP;
66 bool bASIMD;
67
68 // Call Detect()
69 explicit CPUInfo();
70
71 // Turn the cpu info into a string we can show
72 std::string Summarize();
73
74private:
75 // Detects the various cpu features
76 void Detect();
77};
78
79extern CPUInfo cpu_info;
80
81#endif // _CPUDETECT_H_
diff --git a/src/common/src/debug_interface.h b/src/common/src/debug_interface.h
new file mode 100644
index 000000000..317cd0bb4
--- /dev/null
+++ b/src/common/src/debug_interface.h
@@ -0,0 +1,39 @@
1#ifndef _DEBUGINTERFACE_H
2#define _DEBUGINTERFACE_H
3
4#include <string>
5#include <string.h>
6
7class DebugInterface
8{
9protected:
10 virtual ~DebugInterface() {}
11
12public:
13 virtual void disasm(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
14 virtual void getRawMemoryString(int /*memory*/, unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
15 virtual int getInstructionSize(int /*instruction*/) {return 1;}
16 virtual bool isAlive() {return true;}
17 virtual bool isBreakpoint(unsigned int /*address*/) {return false;}
18 virtual void setBreakpoint(unsigned int /*address*/){}
19 virtual void clearBreakpoint(unsigned int /*address*/){}
20 virtual void clearAllBreakpoints() {}
21 virtual void toggleBreakpoint(unsigned int /*address*/){}
22 virtual bool isMemCheck(unsigned int /*address*/) {return false;}
23 virtual void toggleMemCheck(unsigned int /*address*/){}
24 virtual unsigned int readMemory(unsigned int /*address*/){return 0;}
25 virtual void writeExtraMemory(int /*memory*/, unsigned int /*value*/, unsigned int /*address*/) {}
26 virtual unsigned int readExtraMemory(int /*memory*/, unsigned int /*address*/){return 0;}
27 virtual unsigned int readInstruction(unsigned int /*address*/){return 0;}
28 virtual unsigned int getPC() {return 0;}
29 virtual void setPC(unsigned int /*address*/) {}
30 virtual void step() {}
31 virtual void runToBreakpoint() {}
32 virtual void breakNow() {}
33 virtual void insertBLR(unsigned int /*address*/, unsigned int /*value*/) {}
34 virtual void showJitResults(unsigned int /*address*/) {};
35 virtual int getColor(unsigned int /*address*/){return 0xFFFFFFFF;}
36 virtual std::string getDescription(unsigned int /*address*/) = 0;
37};
38
39#endif
diff --git a/src/common/src/extended_trace.cpp b/src/common/src/extended_trace.cpp
new file mode 100644
index 000000000..44815343d
--- /dev/null
+++ b/src/common/src/extended_trace.cpp
@@ -0,0 +1,433 @@
1// --------------------------------------------------------------------------------------
2//
3// Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
4// For companies(Austin,TX): If you would like to get my resume, send an email.
5//
6// The source is free, but if you want to use it, mention my name and e-mail address
7//
8// History:
9// 1.0 Initial version Zoltan Csizmadia
10// 1.1 WhineCube version Masken
11// 1.2 Dolphin version Masken
12//
13// --------------------------------------------------------------------------------------
14
15#if defined(WIN32)
16
17#include <windows.h>
18#include <stdio.h>
19#include "extended_trace.h"
20#include "string_util.h"
21using namespace std;
22
23#include <tchar.h>
24#include <ImageHlp.h>
25
26#define BUFFERSIZE 0x200
27#pragma warning(disable:4996)
28
29// Unicode safe char* -> TCHAR* conversion
30void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut )
31{
32#if defined(UNICODE)||defined(_UNICODE)
33 ULONG index = 0;
34 PCSTR lpAct = lpszIn;
35
36 for( ; ; lpAct++ )
37 {
38 lpszOut[index++] = (TCHAR)(*lpAct);
39 if ( *lpAct == 0 )
40 break;
41 }
42#else
43 // This is trivial :)
44 strcpy( lpszOut, lpszIn );
45#endif
46}
47
48// Let's figure out the path for the symbol files
49// Search path= ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;" + lpszIniPath
50// Note: There is no size check for lpszSymbolPath!
51static void InitSymbolPath( PSTR lpszSymbolPath, PCSTR lpszIniPath )
52{
53 CHAR lpszPath[BUFFERSIZE];
54
55 // Creating the default path
56 // ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;"
57 strcpy( lpszSymbolPath, "." );
58
59 // environment variable _NT_SYMBOL_PATH
60 if ( GetEnvironmentVariableA( "_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE ) )
61 {
62 strcat( lpszSymbolPath, ";" );
63 strcat( lpszSymbolPath, lpszPath );
64 }
65
66 // environment variable _NT_ALTERNATE_SYMBOL_PATH
67 if ( GetEnvironmentVariableA( "_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE ) )
68 {
69 strcat( lpszSymbolPath, ";" );
70 strcat( lpszSymbolPath, lpszPath );
71 }
72
73 // environment variable SYSTEMROOT
74 if ( GetEnvironmentVariableA( "SYSTEMROOT", lpszPath, BUFFERSIZE ) )
75 {
76 strcat( lpszSymbolPath, ";" );
77 strcat( lpszSymbolPath, lpszPath );
78 strcat( lpszSymbolPath, ";" );
79
80 // SYSTEMROOT\System32
81 strcat( lpszSymbolPath, lpszPath );
82 strcat( lpszSymbolPath, "\\System32" );
83 }
84
85 // Add user defined path
86 if ( lpszIniPath != NULL )
87 if ( lpszIniPath[0] != '\0' )
88 {
89 strcat( lpszSymbolPath, ";" );
90 strcat( lpszSymbolPath, lpszIniPath );
91 }
92}
93
94// Uninitialize the loaded symbol files
95BOOL UninitSymInfo() {
96 return SymCleanup( GetCurrentProcess() );
97}
98
99// Initializes the symbol files
100BOOL InitSymInfo( PCSTR lpszInitialSymbolPath )
101{
102 CHAR lpszSymbolPath[BUFFERSIZE];
103 DWORD symOptions = SymGetOptions();
104
105 symOptions |= SYMOPT_LOAD_LINES;
106 symOptions &= ~SYMOPT_UNDNAME;
107 SymSetOptions( symOptions );
108 InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath );
109
110 return SymInitialize( GetCurrentProcess(), lpszSymbolPath, TRUE);
111}
112
113// Get the module name from a given address
114static BOOL GetModuleNameFromAddress( UINT address, LPTSTR lpszModule )
115{
116 BOOL ret = FALSE;
117 IMAGEHLP_MODULE moduleInfo;
118
119 ::ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
120 moduleInfo.SizeOfStruct = sizeof(moduleInfo);
121
122 if ( SymGetModuleInfo( GetCurrentProcess(), (DWORD)address, &moduleInfo ) )
123 {
124 // Got it!
125 PCSTR2LPTSTR( moduleInfo.ModuleName, lpszModule );
126 ret = TRUE;
127 }
128 else
129 // Not found :(
130 _tcscpy( lpszModule, _T("?") );
131
132 return ret;
133}
134
135// Get function prototype and parameter info from ip address and stack address
136static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol )
137{
138 BOOL ret = FALSE;
139 DWORD dwSymSize = 10000;
140 TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?");
141 CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?";
142 LPTSTR lpszParamSep = NULL;
143 LPTSTR lpszParsed = lpszUnDSymbol;
144 PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize );
145
146 ::ZeroMemory( pSym, dwSymSize );
147 pSym->SizeOfStruct = dwSymSize;
148 pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL);
149
150 // Set the default to unknown
151 _tcscpy( lpszSymbol, _T("?") );
152
153 // Get symbol info for IP
154#ifndef _M_X64
155 DWORD dwDisp = 0;
156 if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) )
157#else
158 //makes it compile but hell im not sure if this works...
159 DWORD64 dwDisp = 0;
160 if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) )
161#endif
162 {
163 // Make the symbol readable for humans
164 UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
165 UNDNAME_COMPLETE |
166 UNDNAME_NO_THISTYPE |
167 UNDNAME_NO_SPECIAL_SYMS |
168 UNDNAME_NO_MEMBER_TYPE |
169 UNDNAME_NO_MS_KEYWORDS |
170 UNDNAME_NO_ACCESS_SPECIFIERS );
171
172 // Symbol information is ANSI string
173 PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol );
174
175 // I am just smarter than the symbol file :)
176 if ( _tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0 )
177 _tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)"));
178 else
179 if ( _tcscmp(lpszUnDSymbol, _T("_main")) == 0 )
180 _tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)"));
181 else
182 if ( _tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0 )
183 _tcscpy(lpszUnDSymbol, _T("mainCRTStartup()"));
184 else
185 if ( _tcscmp(lpszUnDSymbol, _T("_wmain")) == 0 )
186 _tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)"));
187 else
188 if ( _tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0 )
189 _tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()"));
190
191 lpszSymbol[0] = _T('\0');
192
193 // Let's go through the stack, and modify the function prototype, and insert the actual
194 // parameter values from the stack
195 if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == NULL && _tcsstr( lpszUnDSymbol, _T("()") ) == NULL)
196 {
197 ULONG index = 0;
198 for( ; ; index++ )
199 {
200 lpszParamSep = _tcschr( lpszParsed, _T(',') );
201 if ( lpszParamSep == NULL )
202 break;
203
204 *lpszParamSep = _T('\0');
205
206 _tcscat( lpszSymbol, lpszParsed );
207 _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) );
208
209 lpszParsed = lpszParamSep + 1;
210 }
211
212 lpszParamSep = _tcschr( lpszParsed, _T(')') );
213 if ( lpszParamSep != NULL )
214 {
215 *lpszParamSep = _T('\0');
216
217 _tcscat( lpszSymbol, lpszParsed );
218 _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) );
219
220 lpszParsed = lpszParamSep + 1;
221 }
222 }
223
224 _tcscat( lpszSymbol, lpszParsed );
225
226 ret = TRUE;
227 }
228 GlobalFree( pSym );
229
230 return ret;
231}
232
233// Get source file name and line number from IP address
234// The output format is: "sourcefile(linenumber)" or
235// "modulename!address" or
236// "address"
237static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
238{
239 BOOL ret = FALSE;
240 IMAGEHLP_LINE lineInfo;
241 DWORD dwDisp;
242 TCHAR lpszFileName[BUFFERSIZE] = _T("");
243 TCHAR lpModuleInfo[BUFFERSIZE] = _T("");
244
245 _tcscpy( lpszSourceInfo, _T("?(?)") );
246
247 ::ZeroMemory( &lineInfo, sizeof( lineInfo ) );
248 lineInfo.SizeOfStruct = sizeof( lineInfo );
249
250 if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) )
251 {
252 // Got it. Let's use "sourcefile(linenumber)" format
253 PCSTR2LPTSTR( lineInfo.FileName, lpszFileName );
254 TCHAR fname[_MAX_FNAME];
255 TCHAR ext[_MAX_EXT];
256 _tsplitpath(lpszFileName, NULL, NULL, fname, ext);
257 _stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber );
258 ret = TRUE;
259 }
260 else
261 {
262 // There is no source file information. :(
263 // Let's use the "modulename!address" format
264 GetModuleNameFromAddress( address, lpModuleInfo );
265
266 if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0'))
267 // There is no modulename information. :((
268 // Let's use the "address" format
269 _stprintf( lpszSourceInfo, _T("0x%08X"), address );
270 else
271 _stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address );
272
273 ret = FALSE;
274 }
275
276 return ret;
277}
278
279void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack)
280{
281 TCHAR symInfo[BUFFERSIZE] = _T("?");
282 TCHAR srcInfo[BUFFERSIZE] = _T("?");
283
284 GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo);
285 GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo);
286 etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n");
287}
288
289void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
290{
291 STACKFRAME callStack;
292 BOOL bResult;
293 CONTEXT context;
294 HANDLE hProcess = GetCurrentProcess();
295
296 // If it's not this thread, let's suspend it, and resume it at the end
297 if ( hThread != GetCurrentThread() )
298 if ( SuspendThread( hThread ) == -1 )
299 {
300 // whaaat ?!
301 etfprint(file, "Call stack info failed\n");
302 return;
303 }
304
305 ::ZeroMemory( &context, sizeof(context) );
306 context.ContextFlags = CONTEXT_FULL;
307
308 if ( !GetThreadContext( hThread, &context ) )
309 {
310 etfprint(file, "Call stack info failed\n");
311 return;
312 }
313
314 ::ZeroMemory( &callStack, sizeof(callStack) );
315#ifndef _M_X64
316 callStack.AddrPC.Offset = context.Eip;
317 callStack.AddrStack.Offset = context.Esp;
318 callStack.AddrFrame.Offset = context.Ebp;
319#else
320 callStack.AddrPC.Offset = context.Rip;
321 callStack.AddrStack.Offset = context.Rsp;
322 callStack.AddrFrame.Offset = context.Rbp;
323#endif
324 callStack.AddrPC.Mode = AddrModeFlat;
325 callStack.AddrStack.Mode = AddrModeFlat;
326 callStack.AddrFrame.Mode = AddrModeFlat;
327
328 etfprint(file, "Call stack info: \n");
329 etfprint(file, lpszMessage);
330
331 PrintFunctionAndSourceInfo(file, callStack);
332
333 for( ULONG index = 0; ; index++ )
334 {
335 bResult = StackWalk(
336 IMAGE_FILE_MACHINE_I386,
337 hProcess,
338 hThread,
339 &callStack,
340 NULL,
341 NULL,
342 SymFunctionTableAccess,
343 SymGetModuleBase,
344 NULL);
345
346 if ( index == 0 )
347 continue;
348
349 if( !bResult || callStack.AddrFrame.Offset == 0 )
350 break;
351
352 PrintFunctionAndSourceInfo(file, callStack);
353
354 }
355
356 if ( hThread != GetCurrentThread() )
357 ResumeThread( hThread );
358}
359
360void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
361{
362 STACKFRAME callStack;
363 BOOL bResult;
364 TCHAR symInfo[BUFFERSIZE] = _T("?");
365 TCHAR srcInfo[BUFFERSIZE] = _T("?");
366 HANDLE hProcess = GetCurrentProcess();
367
368 // If it's not this thread, let's suspend it, and resume it at the end
369 if ( hThread != GetCurrentThread() )
370 if ( SuspendThread( hThread ) == -1 )
371 {
372 // whaaat ?!
373 etfprint(file, "Call stack info failed\n");
374 return;
375 }
376
377 ::ZeroMemory( &callStack, sizeof(callStack) );
378 callStack.AddrPC.Offset = eip;
379 callStack.AddrStack.Offset = esp;
380 callStack.AddrFrame.Offset = ebp;
381 callStack.AddrPC.Mode = AddrModeFlat;
382 callStack.AddrStack.Mode = AddrModeFlat;
383 callStack.AddrFrame.Mode = AddrModeFlat;
384
385 etfprint(file, "Call stack info: \n");
386 etfprint(file, lpszMessage);
387
388 PrintFunctionAndSourceInfo(file, callStack);
389
390 for( ULONG index = 0; ; index++ )
391 {
392 bResult = StackWalk(
393 IMAGE_FILE_MACHINE_I386,
394 hProcess,
395 hThread,
396 &callStack,
397 NULL,
398 NULL,
399 SymFunctionTableAccess,
400 SymGetModuleBase,
401 NULL);
402
403 if ( index == 0 )
404 continue;
405
406 if( !bResult || callStack.AddrFrame.Offset == 0 )
407 break;
408
409 PrintFunctionAndSourceInfo(file, callStack);
410 }
411
412 if ( hThread != GetCurrentThread() )
413 ResumeThread( hThread );
414}
415
416char g_uefbuf[2048];
417
418void etfprintf(FILE *file, const char *format, ...)
419{
420 va_list ap;
421 va_start(ap, format);
422 int len = vsprintf(g_uefbuf, format, ap);
423 fwrite(g_uefbuf, 1, len, file);
424 va_end(ap);
425}
426
427void etfprint(FILE *file, const std::string &text)
428{
429 size_t len = text.length();
430 fwrite(text.data(), 1, len, file);
431}
432
433#endif //WIN32
diff --git a/src/common/src/extended_trace.h b/src/common/src/extended_trace.h
new file mode 100644
index 000000000..6d33eb632
--- /dev/null
+++ b/src/common/src/extended_trace.h
@@ -0,0 +1,53 @@
1// -----------------------------------------------------------------------------------------
2//
3// Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
4// For companies(Austin,TX): If you would like to get my resume, send an email.
5//
6// The source is free, but if you want to use it, mention my name and e-mail address
7//
8// History:
9// 1.0 Initial version Zoltan Csizmadia
10// 1.1 WhineCube version Masken
11// 1.2 Dolphin version Masken
12//
13// ----------------------------------------------------------------------------------------
14
15#ifndef _EXTENDEDTRACE_H_INCLUDED_
16#define _EXTENDEDTRACE_H_INCLUDED_
17
18#if defined(WIN32)
19
20#include <windows.h>
21#include <tchar.h>
22
23#include <string>
24
25#pragma comment( lib, "imagehlp.lib" )
26
27#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath )
28#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
29#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file)
30#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp)
31// class File;
32
33BOOL InitSymInfo( PCSTR );
34BOOL UninitSymInfo();
35void StackTrace(HANDLE, char const* msg, FILE *file);
36void StackTrace(HANDLE, char const* msg, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
37
38// functions by Masken
39void etfprintf(FILE *file, const char *format, ...);
40void etfprint(FILE *file, const std::string &text);
41#define UEFBUFSIZE 2048
42extern char g_uefbuf[UEFBUFSIZE];
43
44#else // not WIN32
45
46#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
47#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
48#define STACKTRACE(file) ((void)0)
49#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
50
51#endif // WIN32
52
53#endif // _EXTENDEDTRACE_H_INCLUDED_
diff --git a/src/common/src/fifo_queue.h b/src/common/src/fifo_queue.h
new file mode 100644
index 000000000..4f5ca5706
--- /dev/null
+++ b/src/common/src/fifo_queue.h
@@ -0,0 +1,115 @@
1
2#ifndef _FIFO_QUEUE_H_
3#define _FIFO_QUEUE_H_
4
5// a simple lockless thread-safe,
6// single reader, single writer queue
7
8#include "atomic.h"
9
10namespace Common
11{
12
13template <typename T>
14class FifoQueue
15{
16public:
17 FifoQueue() : m_size(0)
18 {
19 m_write_ptr = m_read_ptr = new ElementPtr();
20 }
21
22 ~FifoQueue()
23 {
24 // this will empty out the whole queue
25 delete m_read_ptr;
26 }
27
28 u32 Size() const
29 {
30 return m_size;
31 }
32
33 bool Empty() const
34 {
35 //return (m_read_ptr == m_write_ptr);
36 return (0 == m_size);
37 }
38
39 T& Front() const
40 {
41 return *m_read_ptr->current;
42 }
43
44 template <typename Arg>
45 void Push(Arg&& t)
46 {
47 // create the element, add it to the queue
48 m_write_ptr->current = new T(std::forward<Arg>(t));
49 // set the next pointer to a new element ptr
50 // then advance the write pointer
51 m_write_ptr = m_write_ptr->next = new ElementPtr();
52 Common::AtomicIncrement(m_size);
53 }
54
55 void Pop()
56 {
57 Common::AtomicDecrement(m_size);
58 ElementPtr *const tmpptr = m_read_ptr;
59 // advance the read pointer
60 m_read_ptr = m_read_ptr->next;
61 // set the next element to NULL to stop the recursive deletion
62 tmpptr->next = NULL;
63 delete tmpptr; // this also deletes the element
64 }
65
66 bool Pop(T& t)
67 {
68 if (Empty())
69 return false;
70
71 t = std::move(Front());
72 Pop();
73
74 return true;
75 }
76
77 // not thread-safe
78 void Clear()
79 {
80 m_size = 0;
81 delete m_read_ptr;
82 m_write_ptr = m_read_ptr = new ElementPtr();
83 }
84
85private:
86 // stores a pointer to element
87 // and a pointer to the next ElementPtr
88 class ElementPtr
89 {
90 public:
91 ElementPtr() : current(NULL), next(NULL) {}
92
93 ~ElementPtr()
94 {
95 if (current)
96 {
97 delete current;
98 // recusion ftw
99 if (next)
100 delete next;
101 }
102 }
103
104 T *volatile current;
105 ElementPtr *volatile next;
106 };
107
108 ElementPtr *volatile m_write_ptr;
109 ElementPtr *volatile m_read_ptr;
110 volatile u32 m_size;
111};
112
113}
114
115#endif
diff --git a/src/common/src/file_search.cpp b/src/common/src/file_search.cpp
new file mode 100644
index 000000000..ba140ec12
--- /dev/null
+++ b/src/common/src/file_search.cpp
@@ -0,0 +1,106 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#include "common.h"
7#include "common_paths.h"
8#ifndef _WIN32
9#include <sys/types.h>
10#include <dirent.h>
11#else
12#include <windows.h>
13#endif
14
15#include <string>
16#include <algorithm>
17
18#include "file_search.h"
19
20#include "string_util.h"
21
22
23CFileSearch::CFileSearch(const CFileSearch::XStringVector& _rSearchStrings, const CFileSearch::XStringVector& _rDirectories)
24{
25 // Reverse the loop order for speed?
26 for (size_t j = 0; j < _rSearchStrings.size(); j++)
27 {
28 for (size_t i = 0; i < _rDirectories.size(); i++)
29 {
30 FindFiles(_rSearchStrings[j], _rDirectories[i]);
31 }
32 }
33}
34
35
36void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath)
37{
38 std::string GCMSearchPath;
39 BuildCompleteFilename(GCMSearchPath, _strPath, _searchString);
40#ifdef _WIN32
41 WIN32_FIND_DATA findData;
42 HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData);
43
44 if (FindFirst != INVALID_HANDLE_VALUE)
45 {
46 bool bkeepLooping = true;
47
48 while (bkeepLooping)
49 {
50 if (findData.cFileName[0] != '.')
51 {
52 std::string strFilename;
53 BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName));
54 m_FileNames.push_back(strFilename);
55 }
56
57 bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false;
58 }
59 }
60 FindClose(FindFirst);
61
62
63#else
64 // TODO: super lame/broken
65
66 auto end_match(_searchString);
67
68 // assuming we have a "*.blah"-like pattern
69 if (!end_match.empty() && end_match[0] == '*')
70 end_match.erase(0, 1);
71
72 // ugly
73 if (end_match == ".*")
74 end_match.clear();
75
76 DIR* dir = opendir(_strPath.c_str());
77
78 if (!dir)
79 return;
80
81 while (auto const dp = readdir(dir))
82 {
83 std::string found(dp->d_name);
84
85 if ((found != ".") && (found != "..")
86 && (found.size() >= end_match.size())
87 && std::equal(end_match.rbegin(), end_match.rend(), found.rbegin()))
88 {
89 std::string full_name;
90 if (_strPath.c_str()[_strPath.size()-1] == DIR_SEP_CHR)
91 full_name = _strPath + found;
92 else
93 full_name = _strPath + DIR_SEP + found;
94
95 m_FileNames.push_back(full_name);
96 }
97 }
98
99 closedir(dir);
100#endif
101}
102
103const CFileSearch::XStringVector& CFileSearch::GetFileNames() const
104{
105 return m_FileNames;
106}
diff --git a/src/common/src/file_search.h b/src/common/src/file_search.h
new file mode 100644
index 000000000..55aaf4ebe
--- /dev/null
+++ b/src/common/src/file_search.h
@@ -0,0 +1,28 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _FILESEARCH_H_
7#define _FILESEARCH_H_
8
9#include <string>
10#include <vector>
11
12class CFileSearch
13{
14public:
15 typedef std::vector<std::string>XStringVector;
16
17 CFileSearch(const XStringVector& _rSearchStrings, const XStringVector& _rDirectories);
18 const XStringVector& GetFileNames() const;
19
20private:
21
22 void FindFiles(const std::string& _searchString, const std::string& _strPath);
23
24 XStringVector m_FileNames;
25};
26
27#endif // _FILESEARCH_H_
28
diff --git a/src/common/src/file_util.cpp b/src/common/src/file_util.cpp
new file mode 100644
index 000000000..f86414bf3
--- /dev/null
+++ b/src/common/src/file_util.cpp
@@ -0,0 +1,922 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#include "common.h"
7#include "common_paths.h"
8#include "file_util.h"
9#include "string_util.h"
10
11#ifdef _WIN32
12#include <windows.h>
13#include <shlobj.h> // for SHGetFolderPath
14#include <shellapi.h>
15#include <commdlg.h> // for GetSaveFileName
16#include <io.h>
17#include <direct.h> // getcwd
18#else
19#include <sys/param.h>
20#include <sys/types.h>
21#include <dirent.h>
22#include <errno.h>
23#include <stdlib.h>
24#endif
25
26#if defined(__APPLE__)
27#include <CoreFoundation/CFString.h>
28#include <CoreFoundation/CFURL.h>
29#include <CoreFoundation/CFBundle.h>
30#endif
31
32#include <algorithm>
33#include <sys/stat.h>
34
35#include "string_util.h"
36
37#ifndef S_ISDIR
38#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
39#endif
40
41#ifdef BSD4_4
42#define stat64 stat
43#define fstat64 fstat
44#endif
45
46// This namespace has various generic functions related to files and paths.
47// The code still needs a ton of cleanup.
48// REMEMBER: strdup considered harmful!
49namespace File
50{
51
52// Remove any ending forward slashes from directory paths
53// Modifies argument.
54static void StripTailDirSlashes(std::string &fname)
55{
56 if (fname.length() > 1)
57 {
58 size_t i = fname.length() - 1;
59 while (fname[i] == DIR_SEP_CHR)
60 fname[i--] = '\0';
61 }
62 return;
63}
64
65// Returns true if file filename exists
66bool Exists(const std::string &filename)
67{
68 struct stat64 file_info;
69
70 std::string copy(filename);
71 StripTailDirSlashes(copy);
72
73#ifdef _WIN32
74 int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info);
75#else
76 int result = stat64(copy.c_str(), &file_info);
77#endif
78
79 return (result == 0);
80}
81
82// Returns true if filename is a directory
83bool IsDirectory(const std::string &filename)
84{
85 struct stat64 file_info;
86
87 std::string copy(filename);
88 StripTailDirSlashes(copy);
89
90#ifdef _WIN32
91 int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info);
92#else
93 int result = stat64(copy.c_str(), &file_info);
94#endif
95
96 if (result < 0) {
97 WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
98 filename.c_str(), GetLastErrorMsg());
99 return false;
100 }
101
102 return S_ISDIR(file_info.st_mode);
103}
104
105// Deletes a given filename, return true on success
106// Doesn't supports deleting a directory
107bool Delete(const std::string &filename)
108{
109 INFO_LOG(COMMON, "Delete: file %s", filename.c_str());
110
111 // Return true because we care about the file no
112 // being there, not the actual delete.
113 if (!Exists(filename))
114 {
115 WARN_LOG(COMMON, "Delete: %s does not exist", filename.c_str());
116 return true;
117 }
118
119 // We can't delete a directory
120 if (IsDirectory(filename))
121 {
122 WARN_LOG(COMMON, "Delete failed: %s is a directory", filename.c_str());
123 return false;
124 }
125
126#ifdef _WIN32
127 if (!DeleteFile(UTF8ToTStr(filename).c_str()))
128 {
129 WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
130 filename.c_str(), GetLastErrorMsg());
131 return false;
132 }
133#else
134 if (unlink(filename.c_str()) == -1) {
135 WARN_LOG(COMMON, "Delete: unlink failed on %s: %s",
136 filename.c_str(), GetLastErrorMsg());
137 return false;
138 }
139#endif
140
141 return true;
142}
143
144// Returns true if successful, or path already exists.
145bool CreateDir(const std::string &path)
146{
147 INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
148#ifdef _WIN32
149 if (::CreateDirectory(UTF8ToTStr(path).c_str(), NULL))
150 return true;
151 DWORD error = GetLastError();
152 if (error == ERROR_ALREADY_EXISTS)
153 {
154 WARN_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str());
155 return true;
156 }
157 ERROR_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: %i", path.c_str(), error);
158 return false;
159#else
160 if (mkdir(path.c_str(), 0755) == 0)
161 return true;
162
163 int err = errno;
164
165 if (err == EEXIST)
166 {
167 WARN_LOG(COMMON, "CreateDir: mkdir failed on %s: already exists", path.c_str());
168 return true;
169 }
170
171 ERROR_LOG(COMMON, "CreateDir: mkdir failed on %s: %s", path.c_str(), strerror(err));
172 return false;
173#endif
174}
175
176// Creates the full path of fullPath returns true on success
177bool CreateFullPath(const std::string &fullPath)
178{
179 int panicCounter = 100;
180 INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str());
181
182 if (File::Exists(fullPath))
183 {
184 INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str());
185 return true;
186 }
187
188 size_t position = 0;
189 while (true)
190 {
191 // Find next sub path
192 position = fullPath.find(DIR_SEP_CHR, position);
193
194 // we're done, yay!
195 if (position == fullPath.npos)
196 return true;
197
198 // Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
199 std::string const subPath(fullPath.substr(0, position + 1));
200 if (!File::IsDirectory(subPath))
201 File::CreateDir(subPath);
202
203 // A safety check
204 panicCounter--;
205 if (panicCounter <= 0)
206 {
207 ERROR_LOG(COMMON, "CreateFullPath: directory structure is too deep");
208 return false;
209 }
210 position++;
211 }
212}
213
214
215// Deletes a directory filename, returns true on success
216bool DeleteDir(const std::string &filename)
217{
218 INFO_LOG(COMMON, "DeleteDir: directory %s", filename.c_str());
219
220 // check if a directory
221 if (!File::IsDirectory(filename))
222 {
223 ERROR_LOG(COMMON, "DeleteDir: Not a directory %s", filename.c_str());
224 return false;
225 }
226
227#ifdef _WIN32
228 if (::RemoveDirectory(UTF8ToTStr(filename).c_str()))
229 return true;
230#else
231 if (rmdir(filename.c_str()) == 0)
232 return true;
233#endif
234 ERROR_LOG(COMMON, "DeleteDir: %s: %s", filename.c_str(), GetLastErrorMsg());
235
236 return false;
237}
238
239// renames file srcFilename to destFilename, returns true on success
240bool Rename(const std::string &srcFilename, const std::string &destFilename)
241{
242 INFO_LOG(COMMON, "Rename: %s --> %s",
243 srcFilename.c_str(), destFilename.c_str());
244 if (rename(srcFilename.c_str(), destFilename.c_str()) == 0)
245 return true;
246 ERROR_LOG(COMMON, "Rename: failed %s --> %s: %s",
247 srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
248 return false;
249}
250
251// copies file srcFilename to destFilename, returns true on success
252bool Copy(const std::string &srcFilename, const std::string &destFilename)
253{
254 INFO_LOG(COMMON, "Copy: %s --> %s",
255 srcFilename.c_str(), destFilename.c_str());
256#ifdef _WIN32
257 if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE))
258 return true;
259
260 ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
261 srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
262 return false;
263#else
264
265 // buffer size
266#define BSIZE 1024
267
268 char buffer[BSIZE];
269
270 // Open input file
271 FILE *input = fopen(srcFilename.c_str(), "rb");
272 if (!input)
273 {
274 ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s",
275 srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
276 return false;
277 }
278
279 // open output file
280 FILE *output = fopen(destFilename.c_str(), "wb");
281 if (!output)
282 {
283 fclose(input);
284 ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s",
285 srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
286 return false;
287 }
288
289 // copy loop
290 while (!feof(input))
291 {
292 // read input
293 int rnum = fread(buffer, sizeof(char), BSIZE, input);
294 if (rnum != BSIZE)
295 {
296 if (ferror(input) != 0)
297 {
298 ERROR_LOG(COMMON,
299 "Copy: failed reading from source, %s --> %s: %s",
300 srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
301 goto bail;
302 }
303 }
304
305 // write output
306 int wnum = fwrite(buffer, sizeof(char), rnum, output);
307 if (wnum != rnum)
308 {
309 ERROR_LOG(COMMON,
310 "Copy: failed writing to output, %s --> %s: %s",
311 srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
312 goto bail;
313 }
314 }
315 // close files
316 fclose(input);
317 fclose(output);
318 return true;
319bail:
320 if (input)
321 fclose(input);
322 if (output)
323 fclose(output);
324 return false;
325#endif
326}
327
328// Returns the size of filename (64bit)
329u64 GetSize(const std::string &filename)
330{
331 if (!Exists(filename))
332 {
333 WARN_LOG(COMMON, "GetSize: failed %s: No such file", filename.c_str());
334 return 0;
335 }
336
337 if (IsDirectory(filename))
338 {
339 WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str());
340 return 0;
341 }
342
343 struct stat64 buf;
344#ifdef _WIN32
345 if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0)
346#else
347 if (stat64(filename.c_str(), &buf) == 0)
348#endif
349 {
350 DEBUG_LOG(COMMON, "GetSize: %s: %lld",
351 filename.c_str(), (long long)buf.st_size);
352 return buf.st_size;
353 }
354
355 ERROR_LOG(COMMON, "GetSize: Stat failed %s: %s",
356 filename.c_str(), GetLastErrorMsg());
357 return 0;
358}
359
360// Overloaded GetSize, accepts file descriptor
361u64 GetSize(const int fd)
362{
363 struct stat64 buf;
364 if (fstat64(fd, &buf) != 0) {
365 ERROR_LOG(COMMON, "GetSize: stat failed %i: %s",
366 fd, GetLastErrorMsg());
367 return 0;
368 }
369 return buf.st_size;
370}
371
372// Overloaded GetSize, accepts FILE*
373u64 GetSize(FILE *f)
374{
375 // can't use off_t here because it can be 32-bit
376 u64 pos = ftello(f);
377 if (fseeko(f, 0, SEEK_END) != 0) {
378 ERROR_LOG(COMMON, "GetSize: seek failed %p: %s",
379 f, GetLastErrorMsg());
380 return 0;
381 }
382 u64 size = ftello(f);
383 if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) {
384 ERROR_LOG(COMMON, "GetSize: seek failed %p: %s",
385 f, GetLastErrorMsg());
386 return 0;
387 }
388 return size;
389}
390
391// creates an empty file filename, returns true on success
392bool CreateEmptyFile(const std::string &filename)
393{
394 INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
395
396 if (!File::IOFile(filename, "wb"))
397 {
398 ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s",
399 filename.c_str(), GetLastErrorMsg());
400 return false;
401 }
402
403 return true;
404}
405
406
407// Scans the directory tree gets, starting from _Directory and adds the
408// results into parentEntry. Returns the number of files+directories found
409u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
410{
411 INFO_LOG(COMMON, "ScanDirectoryTree: directory %s", directory.c_str());
412 // How many files + directories we found
413 u32 foundEntries = 0;
414#ifdef _WIN32
415 // Find the first file in the directory.
416 WIN32_FIND_DATA ffd;
417
418 HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd);
419 if (hFind == INVALID_HANDLE_VALUE)
420 {
421 FindClose(hFind);
422 return foundEntries;
423 }
424 // windows loop
425 do
426 {
427 FSTEntry entry;
428 const std::string virtualName(TStrToUTF8(ffd.cFileName));
429#else
430 struct dirent dirent, *result = NULL;
431
432 DIR *dirp = opendir(directory.c_str());
433 if (!dirp)
434 return 0;
435
436 // non windows loop
437 while (!readdir_r(dirp, &dirent, &result) && result)
438 {
439 FSTEntry entry;
440 const std::string virtualName(result->d_name);
441#endif
442 // check for "." and ".."
443 if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
444 ((virtualName[0] == '.') && (virtualName[1] == '.') &&
445 (virtualName[2] == '\0')))
446 continue;
447 entry.virtualName = virtualName;
448 entry.physicalName = directory;
449 entry.physicalName += DIR_SEP + entry.virtualName;
450
451 if (IsDirectory(entry.physicalName.c_str()))
452 {
453 entry.isDirectory = true;
454 // is a directory, lets go inside
455 entry.size = ScanDirectoryTree(entry.physicalName, entry);
456 foundEntries += (u32)entry.size;
457 }
458 else
459 { // is a file
460 entry.isDirectory = false;
461 entry.size = GetSize(entry.physicalName.c_str());
462 }
463 ++foundEntries;
464 // Push into the tree
465 parentEntry.children.push_back(entry);
466#ifdef _WIN32
467 } while (FindNextFile(hFind, &ffd) != 0);
468 FindClose(hFind);
469#else
470 }
471 closedir(dirp);
472#endif
473 // Return number of entries found.
474 return foundEntries;
475}
476
477
478// Deletes the given directory and anything under it. Returns true on success.
479bool DeleteDirRecursively(const std::string &directory)
480{
481 INFO_LOG(COMMON, "DeleteDirRecursively: %s", directory.c_str());
482#ifdef _WIN32
483 // Find the first file in the directory.
484 WIN32_FIND_DATA ffd;
485 HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd);
486
487 if (hFind == INVALID_HANDLE_VALUE)
488 {
489 FindClose(hFind);
490 return false;
491 }
492
493 // windows loop
494 do
495 {
496 const std::string virtualName(TStrToUTF8(ffd.cFileName));
497#else
498 struct dirent dirent, *result = NULL;
499 DIR *dirp = opendir(directory.c_str());
500 if (!dirp)
501 return false;
502
503 // non windows loop
504 while (!readdir_r(dirp, &dirent, &result) && result)
505 {
506 const std::string virtualName = result->d_name;
507#endif
508
509 // check for "." and ".."
510 if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
511 ((virtualName[0] == '.') && (virtualName[1] == '.') &&
512 (virtualName[2] == '\0')))
513 continue;
514
515 std::string newPath = directory + DIR_SEP_CHR + virtualName;
516 if (IsDirectory(newPath))
517 {
518 if (!DeleteDirRecursively(newPath))
519 {
520 #ifndef _WIN32
521 closedir(dirp);
522 #endif
523
524 return false;
525 }
526 }
527 else
528 {
529 if (!File::Delete(newPath))
530 {
531 #ifndef _WIN32
532 closedir(dirp);
533 #endif
534
535 return false;
536 }
537 }
538
539#ifdef _WIN32
540 } while (FindNextFile(hFind, &ffd) != 0);
541 FindClose(hFind);
542#else
543 }
544 closedir(dirp);
545#endif
546 File::DeleteDir(directory);
547
548 return true;
549}
550
551// Create directory and copy contents (does not overwrite existing files)
552void CopyDir(const std::string &source_path, const std::string &dest_path)
553{
554#ifndef _WIN32
555 if (source_path == dest_path) return;
556 if (!File::Exists(source_path)) return;
557 if (!File::Exists(dest_path)) File::CreateFullPath(dest_path);
558
559 struct dirent dirent, *result = NULL;
560 DIR *dirp = opendir(source_path.c_str());
561 if (!dirp) return;
562
563 while (!readdir_r(dirp, &dirent, &result) && result)
564 {
565 const std::string virtualName(result->d_name);
566 // check for "." and ".."
567 if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
568 ((virtualName[0] == '.') && (virtualName[1] == '.') &&
569 (virtualName[2] == '\0')))
570 continue;
571
572 std::string source, dest;
573 source = source_path + virtualName;
574 dest = dest_path + virtualName;
575 if (IsDirectory(source))
576 {
577 source += '/';
578 dest += '/';
579 if (!File::Exists(dest)) File::CreateFullPath(dest);
580 CopyDir(source, dest);
581 }
582 else if (!File::Exists(dest)) File::Copy(source, dest);
583 }
584 closedir(dirp);
585#endif
586}
587
588// Returns the current directory
589std::string GetCurrentDir()
590{
591 char *dir;
592 // Get the current working directory (getcwd uses malloc)
593 if (!(dir = __getcwd(NULL, 0))) {
594
595 ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
596 GetLastErrorMsg());
597 return NULL;
598 }
599 std::string strDir = dir;
600 free(dir);
601 return strDir;
602}
603
604// Sets the current directory to the given directory
605bool SetCurrentDir(const std::string &directory)
606{
607 return __chdir(directory.c_str()) == 0;
608}
609
610#if defined(__APPLE__)
611std::string GetBundleDirectory()
612{
613 CFURLRef BundleRef;
614 char AppBundlePath[MAXPATHLEN];
615 // Get the main bundle for the app
616 BundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
617 CFStringRef BundlePath = CFURLCopyFileSystemPath(BundleRef, kCFURLPOSIXPathStyle);
618 CFStringGetFileSystemRepresentation(BundlePath, AppBundlePath, sizeof(AppBundlePath));
619 CFRelease(BundleRef);
620 CFRelease(BundlePath);
621
622 return AppBundlePath;
623}
624#endif
625
626#ifdef _WIN32
627std::string& GetExeDirectory()
628{
629 static std::string DolphinPath;
630 if (DolphinPath.empty())
631 {
632 TCHAR Dolphin_exe_Path[2048];
633 GetModuleFileName(NULL, Dolphin_exe_Path, 2048);
634 DolphinPath = TStrToUTF8(Dolphin_exe_Path);
635 DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
636 }
637 return DolphinPath;
638}
639#endif
640
641std::string GetSysDirectory()
642{
643 std::string sysDir;
644
645#if defined (__APPLE__)
646 sysDir = GetBundleDirectory();
647 sysDir += DIR_SEP;
648 sysDir += SYSDATA_DIR;
649#else
650 sysDir = SYSDATA_DIR;
651#endif
652 sysDir += DIR_SEP;
653
654 INFO_LOG(COMMON, "GetSysDirectory: Setting to %s:", sysDir.c_str());
655 return sysDir;
656}
657
658// Returns a string with a Dolphin data dir or file in the user's home
659// directory. To be used in "multi-user" mode (that is, installed).
660//const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath)
661//{
662// static std::string paths[NUM_PATH_INDICES];
663//
664// // Set up all paths and files on the first run
665// if (paths[D_USER_IDX].empty())
666// {
667//#ifdef _WIN32
668// paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
669//#else
670// if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR))
671// paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
672// else
673// paths[D_USER_IDX] = std::string(getenv("HOME") ?
674// getenv("HOME") : getenv("PWD") ?
675// getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
676//#endif
677//
678// paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
679// paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP;
680// paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
681// paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
682// paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP;
683// paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
684// paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
685// paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP;
686// paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP;
687// paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP;
688// paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP;
689// paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP;
690// paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP;
691// paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG;
692// paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG;
693// paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG;
694// }
695//
696// if (!newPath.empty())
697// {
698// if (!File::IsDirectory(newPath))
699// {
700// WARN_LOG(COMMON, "Invalid path specified %s", newPath.c_str());
701// return paths[DirIDX];
702// }
703// else
704// {
705// paths[DirIDX] = newPath;
706// }
707//
708// switch (DirIDX)
709// {
710// case D_WIIROOT_IDX:
711// paths[D_WIIUSER_IDX] = paths[D_WIIROOT_IDX] + DIR_SEP;
712// paths[D_WIISYSCONF_IDX] = paths[D_WIIUSER_IDX] + WII_SYSCONF_DIR + DIR_SEP;
713// paths[F_WIISYSCONF_IDX] = paths[D_WIISYSCONF_IDX] + WII_SYSCONF;
714// break;
715//
716// case D_USER_IDX:
717// paths[D_GCUSER_IDX] = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP;
718// paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR;
719// paths[D_WIIUSER_IDX] = paths[D_WIIROOT_IDX] + DIR_SEP;
720// paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
721// paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP;
722// paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
723// paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
724// paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP;
725// paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
726// paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
727// paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP;
728// paths[D_OPENCL_IDX] = paths[D_USER_IDX] + OPENCL_DIR DIR_SEP;
729// paths[D_HIRESTEXTURES_IDX] = paths[D_USER_IDX] + HIRES_TEXTURES_DIR DIR_SEP;
730// paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP;
731// paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP;
732// paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP;
733// paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP;
734// paths[D_DUMPDSP_IDX] = paths[D_DUMP_IDX] + DUMP_DSP_DIR DIR_SEP;
735// paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP;
736// paths[D_MAILLOGS_IDX] = paths[D_LOGS_IDX] + MAIL_LOGS_DIR DIR_SEP;
737// paths[D_WIISYSCONF_IDX] = paths[D_WIIUSER_IDX] + WII_SYSCONF_DIR DIR_SEP;
738// paths[D_THEMES_IDX] = paths[D_USER_IDX] + THEMES_DIR DIR_SEP;
739// paths[F_DOLPHINCONFIG_IDX] = paths[D_CONFIG_IDX] + DOLPHIN_CONFIG;
740// paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG;
741// paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG;
742// paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG;
743// paths[F_WIISYSCONF_IDX] = paths[D_WIISYSCONF_IDX] + WII_SYSCONF;
744// paths[F_RAMDUMP_IDX] = paths[D_DUMP_IDX] + RAM_DUMP;
745// paths[F_ARAMDUMP_IDX] = paths[D_DUMP_IDX] + ARAM_DUMP;
746// paths[F_FAKEVMEMDUMP_IDX] = paths[D_DUMP_IDX] + FAKEVMEM_DUMP;
747// paths[F_GCSRAM_IDX] = paths[D_GCUSER_IDX] + GC_SRAM;
748// break;
749//
750// case D_CONFIG_IDX:
751// paths[F_DOLPHINCONFIG_IDX] = paths[D_CONFIG_IDX] + DOLPHIN_CONFIG;
752// paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG;
753// paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG;
754// break;
755//
756// case D_DUMP_IDX:
757// paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP;
758// paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP;
759// paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP;
760// break;
761//
762// case D_LOGS_IDX:
763// paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG;
764// }
765// }
766//
767// return paths[DirIDX];
768//}
769
770std::string GetThemeDir(const std::string& theme_name)
771{
772 std::string dir = File::GetUserPath(D_THEMES_IDX) + theme_name + "/";
773
774#if !defined(_WIN32)
775 // If theme does not exist in user's dir load from shared directory
776 if (!File::Exists(dir))
777 dir = SHARED_USER_DIR THEMES_DIR "/" + theme_name + "/";
778#endif
779
780 return dir;
781}
782
783bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
784{
785 return File::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size());
786}
787
788bool ReadFileToString(bool text_file, const char *filename, std::string &str)
789{
790 File::IOFile file(filename, text_file ? "r" : "rb");
791 auto const f = file.GetHandle();
792
793 if (!f)
794 return false;
795
796 str.resize(GetSize(f));
797 return file.ReadArray(&str[0], str.size());
798}
799
800IOFile::IOFile()
801 : m_file(NULL), m_good(true)
802{}
803
804IOFile::IOFile(std::FILE* file)
805 : m_file(file), m_good(true)
806{}
807
808IOFile::IOFile(const std::string& filename, const char openmode[])
809 : m_file(NULL), m_good(true)
810{
811 Open(filename, openmode);
812}
813
814IOFile::~IOFile()
815{
816 Close();
817}
818
819IOFile::IOFile(IOFile&& other)
820 : m_file(NULL), m_good(true)
821{
822 Swap(other);
823}
824
825IOFile& IOFile::operator=(IOFile&& other)
826{
827 Swap(other);
828 return *this;
829}
830
831void IOFile::Swap(IOFile& other)
832{
833 std::swap(m_file, other.m_file);
834 std::swap(m_good, other.m_good);
835}
836
837bool IOFile::Open(const std::string& filename, const char openmode[])
838{
839 Close();
840#ifdef _WIN32
841 _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str());
842#else
843 m_file = fopen(filename.c_str(), openmode);
844#endif
845
846 m_good = IsOpen();
847 return m_good;
848}
849
850bool IOFile::Close()
851{
852 if (!IsOpen() || 0 != std::fclose(m_file))
853 m_good = false;
854
855 m_file = NULL;
856 return m_good;
857}
858
859std::FILE* IOFile::ReleaseHandle()
860{
861 std::FILE* const ret = m_file;
862 m_file = NULL;
863 return ret;
864}
865
866void IOFile::SetHandle(std::FILE* file)
867{
868 Close();
869 Clear();
870 m_file = file;
871}
872
873u64 IOFile::GetSize()
874{
875 if (IsOpen())
876 return File::GetSize(m_file);
877 else
878 return 0;
879}
880
881bool IOFile::Seek(s64 off, int origin)
882{
883 if (!IsOpen() || 0 != fseeko(m_file, off, origin))
884 m_good = false;
885
886 return m_good;
887}
888
889u64 IOFile::Tell()
890{
891 if (IsOpen())
892 return ftello(m_file);
893 else
894 return -1;
895}
896
897bool IOFile::Flush()
898{
899 if (!IsOpen() || 0 != std::fflush(m_file))
900 m_good = false;
901
902 return m_good;
903}
904
905bool IOFile::Resize(u64 size)
906{
907 if (!IsOpen() || 0 !=
908#ifdef _WIN32
909 // ector: _chsize sucks, not 64-bit safe
910 // F|RES: changed to _chsize_s. i think it is 64-bit safe
911 _chsize_s(_fileno(m_file), size)
912#else
913 // TODO: handle 64bit and growing
914 ftruncate(fileno(m_file), size)
915#endif
916 )
917 m_good = false;
918
919 return m_good;
920}
921
922} // namespace
diff --git a/src/common/src/file_util.h b/src/common/src/file_util.h
new file mode 100644
index 000000000..a6bd085ab
--- /dev/null
+++ b/src/common/src/file_util.h
@@ -0,0 +1,232 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _FILEUTIL_H_
7#define _FILEUTIL_H_
8
9#include <fstream>
10#include <cstdio>
11#include <string>
12#include <vector>
13#include <string.h>
14
15#include "common.h"
16#include "string_util.h"
17
18// User directory indices for GetUserPath
19enum {
20 D_USER_IDX,
21 D_GCUSER_IDX,
22 D_WIIROOT_IDX,
23 D_WIIUSER_IDX,
24 D_CONFIG_IDX,
25 D_GAMECONFIG_IDX,
26 D_MAPS_IDX,
27 D_CACHE_IDX,
28 D_SHADERCACHE_IDX,
29 D_SHADERS_IDX,
30 D_STATESAVES_IDX,
31 D_SCREENSHOTS_IDX,
32 D_OPENCL_IDX,
33 D_HIRESTEXTURES_IDX,
34 D_DUMP_IDX,
35 D_DUMPFRAMES_IDX,
36 D_DUMPAUDIO_IDX,
37 D_DUMPTEXTURES_IDX,
38 D_DUMPDSP_IDX,
39 D_LOGS_IDX,
40 D_MAILLOGS_IDX,
41 D_WIISYSCONF_IDX,
42 D_WIIWC24_IDX,
43 D_THEMES_IDX,
44 F_DOLPHINCONFIG_IDX,
45 F_DEBUGGERCONFIG_IDX,
46 F_LOGGERCONFIG_IDX,
47 F_MAINLOG_IDX,
48 F_WIISYSCONF_IDX,
49 F_RAMDUMP_IDX,
50 F_ARAMDUMP_IDX,
51 F_FAKEVMEMDUMP_IDX,
52 F_GCSRAM_IDX,
53 NUM_PATH_INDICES
54};
55
56namespace File
57{
58
59// FileSystem tree node/
60struct FSTEntry
61{
62 bool isDirectory;
63 u64 size; // file length or number of entries from children
64 std::string physicalName; // name on disk
65 std::string virtualName; // name in FST names table
66 std::vector<FSTEntry> children;
67};
68
69// Returns true if file filename exists
70bool Exists(const std::string &filename);
71
72// Returns true if filename is a directory
73bool IsDirectory(const std::string &filename);
74
75// Returns the size of filename (64bit)
76u64 GetSize(const std::string &filename);
77
78// Overloaded GetSize, accepts file descriptor
79u64 GetSize(const int fd);
80
81// Overloaded GetSize, accepts FILE*
82u64 GetSize(FILE *f);
83
84// Returns true if successful, or path already exists.
85bool CreateDir(const std::string &filename);
86
87// Creates the full path of fullPath returns true on success
88bool CreateFullPath(const std::string &fullPath);
89
90// Deletes a given filename, return true on success
91// Doesn't supports deleting a directory
92bool Delete(const std::string &filename);
93
94// Deletes a directory filename, returns true on success
95bool DeleteDir(const std::string &filename);
96
97// renames file srcFilename to destFilename, returns true on success
98bool Rename(const std::string &srcFilename, const std::string &destFilename);
99
100// copies file srcFilename to destFilename, returns true on success
101bool Copy(const std::string &srcFilename, const std::string &destFilename);
102
103// creates an empty file filename, returns true on success
104bool CreateEmptyFile(const std::string &filename);
105
106// Scans the directory tree gets, starting from _Directory and adds the
107// results into parentEntry. Returns the number of files+directories found
108u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry);
109
110// deletes the given directory and anything under it. Returns true on success.
111bool DeleteDirRecursively(const std::string &directory);
112
113// Returns the current directory
114std::string GetCurrentDir();
115
116// Create directory and copy contents (does not overwrite existing files)
117void CopyDir(const std::string &source_path, const std::string &dest_path);
118
119// Set the current directory to given directory
120bool SetCurrentDir(const std::string &directory);
121
122// Returns a pointer to a string with a Dolphin data dir in the user's home
123// directory. To be used in "multi-user" mode (that is, installed).
124const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath="");
125
126// probably doesn't belong here
127std::string GetThemeDir(const std::string& theme_name);
128
129// Returns the path to where the sys file are
130std::string GetSysDirectory();
131
132#ifdef __APPLE__
133std::string GetBundleDirectory();
134#endif
135
136#ifdef _WIN32
137std::string &GetExeDirectory();
138#endif
139
140bool WriteStringToFile(bool text_file, const std::string &str, const char *filename);
141bool ReadFileToString(bool text_file, const char *filename, std::string &str);
142
143// simple wrapper for cstdlib file functions to
144// hopefully will make error checking easier
145// and make forgetting an fclose() harder
146class IOFile : public NonCopyable
147{
148public:
149 IOFile();
150 IOFile(std::FILE* file);
151 IOFile(const std::string& filename, const char openmode[]);
152
153 ~IOFile();
154
155 IOFile(IOFile&& other);
156 IOFile& operator=(IOFile&& other);
157
158 void Swap(IOFile& other);
159
160 bool Open(const std::string& filename, const char openmode[]);
161 bool Close();
162
163 template <typename T>
164 bool ReadArray(T* data, size_t length)
165 {
166 if (!IsOpen() || length != std::fread(data, sizeof(T), length, m_file))
167 m_good = false;
168
169 return m_good;
170 }
171
172 template <typename T>
173 bool WriteArray(const T* data, size_t length)
174 {
175 if (!IsOpen() || length != std::fwrite(data, sizeof(T), length, m_file))
176 m_good = false;
177
178 return m_good;
179 }
180
181 bool ReadBytes(void* data, size_t length)
182 {
183 return ReadArray(reinterpret_cast<char*>(data), length);
184 }
185
186 bool WriteBytes(const void* data, size_t length)
187 {
188 return WriteArray(reinterpret_cast<const char*>(data), length);
189 }
190
191 bool IsOpen() { return NULL != m_file; }
192
193 // m_good is set to false when a read, write or other function fails
194 bool IsGood() { return m_good; }
195 operator void*() { return m_good ? m_file : NULL; }
196
197 std::FILE* ReleaseHandle();
198
199 std::FILE* GetHandle() { return m_file; }
200
201 void SetHandle(std::FILE* file);
202
203 bool Seek(s64 off, int origin);
204 u64 Tell();
205 u64 GetSize();
206 bool Resize(u64 size);
207 bool Flush();
208
209 // clear error state
210 void Clear() { m_good = true; std::clearerr(m_file); }
211
212 std::FILE* m_file;
213 bool m_good;
214private:
215 IOFile(IOFile&);
216 IOFile& operator=(IOFile& other);
217};
218
219} // namespace
220
221// To deal with Windows being dumb at unicode:
222template <typename T>
223void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode)
224{
225#ifdef _WIN32
226 fstream.open(UTF8ToTStr(filename).c_str(), openmode);
227#else
228 fstream.open(filename.c_str(), openmode);
229#endif
230}
231
232#endif
diff --git a/src/common/src/fixed_size_queue.h b/src/common/src/fixed_size_queue.h
new file mode 100644
index 000000000..4045dfa33
--- /dev/null
+++ b/src/common/src/fixed_size_queue.h
@@ -0,0 +1,75 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _FIXED_SIZE_QUEUE_H_
7#define _FIXED_SIZE_QUEUE_H_
8
9// STL-look-a-like interface, but name is mixed case to distinguish it clearly from the
10// real STL classes.
11
12// Not fully featured, no safety checking yet. Add features as needed.
13
14// TODO: "inline" storage?
15
16template <class T, int N>
17class fixed_size_queue.h
18{
19 T *storage;
20 int head;
21 int tail;
22 int count; // sacrifice 4 bytes for a simpler implementation. may optimize away in the future.
23
24 // Make copy constructor private for now.
25 fixed_size_queue.h(fixed_size_queue.h &other) { }
26
27public:
28 fixed_size_queue.h()
29 {
30 storage = new T[N];
31 clear();
32 }
33
34 ~fixed_size_queue.h()
35 {
36 delete [] storage;
37 }
38
39 void clear() {
40 head = 0;
41 tail = 0;
42 count = 0;
43 }
44
45 void push(T t) {
46 storage[tail] = t;
47 tail++;
48 if (tail == N)
49 tail = 0;
50 count++;
51 }
52
53 void pop() {
54 head++;
55 if (head == N)
56 head = 0;
57 count--;
58 }
59
60 T pop_front() {
61 const T &temp = storage[head];
62 pop();
63 return temp;
64 }
65
66 T &front() { return storage[head]; }
67 const T &front() const { return storage[head]; }
68
69 size_t size() const {
70 return count;
71 }
72};
73
74#endif // _FIXED_SIZE_QUEUE_H_
75
diff --git a/src/common/src/hash.cpp b/src/common/src/hash.cpp
new file mode 100644
index 000000000..39c636419
--- /dev/null
+++ b/src/common/src/hash.cpp
@@ -0,0 +1,520 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#include "hash.h"
7#if _M_SSE >= 0x402
8#include "cpu_detect.h"
9#include <nmmintrin.h>
10#endif
11
12static u64 (*ptrHashFunction)(const u8 *src, int len, u32 samples) = &GetMurmurHash3;
13
14// uint32_t
15// WARNING - may read one more byte!
16// Implementation from Wikipedia.
17u32 HashFletcher(const u8* data_u8, size_t length)
18{
19 const u16* data = (const u16*)data_u8; /* Pointer to the data to be summed */
20 size_t len = (length + 1) / 2; /* Length in 16-bit words */
21 u32 sum1 = 0xffff, sum2 = 0xffff;
22
23 while (len)
24 {
25 size_t tlen = len > 360 ? 360 : len;
26 len -= tlen;
27
28 do {
29 sum1 += *data++;
30 sum2 += sum1;
31 }
32 while (--tlen);
33
34 sum1 = (sum1 & 0xffff) + (sum1 >> 16);
35 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
36 }
37
38 // Second reduction step to reduce sums to 16 bits
39 sum1 = (sum1 & 0xffff) + (sum1 >> 16);
40 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
41 return(sum2 << 16 | sum1);
42}
43
44
45// Implementation from Wikipedia
46// Slightly slower than Fletcher above, but slightly more reliable.
47#define MOD_ADLER 65521
48// data: Pointer to the data to be summed; len is in bytes
49u32 HashAdler32(const u8* data, size_t len)
50{
51 u32 a = 1, b = 0;
52
53 while (len)
54 {
55 size_t tlen = len > 5550 ? 5550 : len;
56 len -= tlen;
57
58 do
59 {
60 a += *data++;
61 b += a;
62 }
63 while (--tlen);
64
65 a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER);
66 b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
67 }
68
69 // It can be shown that a <= 0x1013a here, so a single subtract will do.
70 if (a >= MOD_ADLER)
71 {
72 a -= MOD_ADLER;
73 }
74
75 // It can be shown that b can reach 0xfff87 here.
76 b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
77
78 if (b >= MOD_ADLER)
79 {
80 b -= MOD_ADLER;
81 }
82
83 return((b << 16) | a);
84}
85
86// Stupid hash - but can't go back now :)
87// Don't use for new things. At least it's reasonably fast.
88u32 HashEctor(const u8* ptr, int length)
89{
90 u32 crc = 0;
91
92 for (int i = 0; i < length; i++)
93 {
94 crc ^= ptr[i];
95 crc = (crc << 3) | (crc >> 29);
96 }
97
98 return(crc);
99}
100
101
102#ifdef _M_X64
103
104//-----------------------------------------------------------------------------
105// Block read - if your platform needs to do endian-swapping or can only
106// handle aligned reads, do the conversion here
107
108inline u64 getblock(const u64 * p, int i)
109{
110 return p[i];
111}
112
113//----------
114// Block mix - combine the key bits with the hash bits and scramble everything
115
116inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
117{
118 k1 *= c1;
119 k1 = _rotl64(k1,23);
120 k1 *= c2;
121 h1 ^= k1;
122 h1 += h2;
123
124 h2 = _rotl64(h2,41);
125
126 k2 *= c2;
127 k2 = _rotl64(k2,23);
128 k2 *= c1;
129 h2 ^= k2;
130 h2 += h1;
131
132 h1 = h1*3+0x52dce729;
133 h2 = h2*3+0x38495ab5;
134
135 c1 = c1*5+0x7b7d159c;
136 c2 = c2*5+0x6bce6396;
137}
138
139//----------
140// Finalization mix - avalanches all bits to within 0.05% bias
141
142inline u64 fmix64(u64 k)
143{
144 k ^= k >> 33;
145 k *= 0xff51afd7ed558ccd;
146 k ^= k >> 33;
147 k *= 0xc4ceb9fe1a85ec53;
148 k ^= k >> 33;
149
150 return k;
151}
152
153u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
154{
155 const u8 * data = (const u8*)src;
156 const int nblocks = len / 16;
157 u32 Step = (len / 8);
158 if(samples == 0) samples = max(Step, 1u);
159 Step = Step / samples;
160 if(Step < 1) Step = 1;
161
162 u64 h1 = 0x9368e53c2f6af274;
163 u64 h2 = 0x586dcd208f7cd3fd;
164
165 u64 c1 = 0x87c37b91114253d5;
166 u64 c2 = 0x4cf5ad432745937f;
167
168
169 //----------
170 // body
171
172 const u64 * blocks = (const u64 *)(data);
173
174 for(int i = 0; i < nblocks; i+=Step)
175 {
176 u64 k1 = getblock(blocks,i*2+0);
177 u64 k2 = getblock(blocks,i*2+1);
178
179 bmix64(h1,h2,k1,k2,c1,c2);
180 }
181
182 //----------
183 // tail
184
185 const u8 * tail = (const u8*)(data + nblocks*16);
186
187 u64 k1 = 0;
188 u64 k2 = 0;
189
190 switch(len & 15)
191 {
192 case 15: k2 ^= u64(tail[14]) << 48;
193 case 14: k2 ^= u64(tail[13]) << 40;
194 case 13: k2 ^= u64(tail[12]) << 32;
195 case 12: k2 ^= u64(tail[11]) << 24;
196 case 11: k2 ^= u64(tail[10]) << 16;
197 case 10: k2 ^= u64(tail[ 9]) << 8;
198 case 9: k2 ^= u64(tail[ 8]) << 0;
199
200 case 8: k1 ^= u64(tail[ 7]) << 56;
201 case 7: k1 ^= u64(tail[ 6]) << 48;
202 case 6: k1 ^= u64(tail[ 5]) << 40;
203 case 5: k1 ^= u64(tail[ 4]) << 32;
204 case 4: k1 ^= u64(tail[ 3]) << 24;
205 case 3: k1 ^= u64(tail[ 2]) << 16;
206 case 2: k1 ^= u64(tail[ 1]) << 8;
207 case 1: k1 ^= u64(tail[ 0]) << 0;
208 bmix64(h1,h2,k1,k2,c1,c2);
209 };
210
211 //----------
212 // finalization
213
214 h2 ^= len;
215
216 h1 += h2;
217 h2 += h1;
218
219 h1 = fmix64(h1);
220 h2 = fmix64(h2);
221
222 h1 += h2;
223
224 return h1;
225}
226
227
228// CRC32 hash using the SSE4.2 instruction
229u64 GetCRC32(const u8 *src, int len, u32 samples)
230{
231#if _M_SSE >= 0x402
232 u64 h = len;
233 u32 Step = (len / 8);
234 const u64 *data = (const u64 *)src;
235 const u64 *end = data + Step;
236 if(samples == 0) samples = max(Step, 1u);
237 Step = Step / samples;
238 if(Step < 1) Step = 1;
239 while(data < end)
240 {
241 h = _mm_crc32_u64(h, data[0]);
242 data += Step;
243 }
244
245 const u8 *data2 = (const u8*)end;
246 return _mm_crc32_u64(h, u64(data2[0]));
247#else
248 return 0;
249#endif
250}
251
252
253/*
254 * NOTE: This hash function is used for custom texture loading/dumping, so
255 * it should not be changed, which would require all custom textures to be
256 * recalculated for their new hash values. If the hashing function is
257 * changed, make sure this one is still used when the legacy parameter is
258 * true.
259 */
260u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
261{
262 const u64 m = 0xc6a4a7935bd1e995;
263 u64 h = len * m;
264 const int r = 47;
265 u32 Step = (len / 8);
266 const u64 *data = (const u64 *)src;
267 const u64 *end = data + Step;
268 if(samples == 0) samples = max(Step, 1u);
269 Step = Step / samples;
270 if(Step < 1) Step = 1;
271 while(data < end)
272 {
273 u64 k = data[0];
274 data+=Step;
275 k *= m;
276 k ^= k >> r;
277 k *= m;
278 h ^= k;
279 h *= m;
280 }
281
282 const u8 * data2 = (const u8*)end;
283
284 switch(len & 7)
285 {
286 case 7: h ^= u64(data2[6]) << 48;
287 case 6: h ^= u64(data2[5]) << 40;
288 case 5: h ^= u64(data2[4]) << 32;
289 case 4: h ^= u64(data2[3]) << 24;
290 case 3: h ^= u64(data2[2]) << 16;
291 case 2: h ^= u64(data2[1]) << 8;
292 case 1: h ^= u64(data2[0]);
293 h *= m;
294 };
295
296 h ^= h >> r;
297 h *= m;
298 h ^= h >> r;
299
300 return h;
301}
302#else
303// CRC32 hash using the SSE4.2 instruction
304u64 GetCRC32(const u8 *src, int len, u32 samples)
305{
306#if _M_SSE >= 0x402
307 u32 h = len;
308 u32 Step = (len/4);
309 const u32 *data = (const u32 *)src;
310 const u32 *end = data + Step;
311 if(samples == 0) samples = max(Step, 1u);
312 Step = Step / samples;
313 if(Step < 1) Step = 1;
314 while(data < end)
315 {
316 h = _mm_crc32_u32(h, data[0]);
317 data += Step;
318 }
319
320 const u8 *data2 = (const u8*)end;
321 return (u64)_mm_crc32_u32(h, u32(data2[0]));
322#else
323 return 0;
324#endif
325}
326
327//-----------------------------------------------------------------------------
328// Block read - if your platform needs to do endian-swapping or can only
329// handle aligned reads, do the conversion here
330
331inline u32 getblock(const u32 * p, int i)
332{
333 return p[i];
334}
335
336//----------
337// Finalization mix - force all bits of a hash block to avalanche
338
339// avalanches all bits to within 0.25% bias
340
341inline u32 fmix32(u32 h)
342{
343 h ^= h >> 16;
344 h *= 0x85ebca6b;
345 h ^= h >> 13;
346 h *= 0xc2b2ae35;
347 h ^= h >> 16;
348
349 return h;
350}
351
352inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2)
353{
354 k1 *= c1;
355 k1 = _rotl(k1,11);
356 k1 *= c2;
357 h1 ^= k1;
358 h1 += h2;
359
360 h2 = _rotl(h2,17);
361
362 k2 *= c2;
363 k2 = _rotl(k2,11);
364 k2 *= c1;
365 h2 ^= k2;
366 h2 += h1;
367
368 h1 = h1*3+0x52dce729;
369 h2 = h2*3+0x38495ab5;
370
371 c1 = c1*5+0x7b7d159c;
372 c2 = c2*5+0x6bce6396;
373}
374
375//----------
376
377u64 GetMurmurHash3(const u8* src, int len, u32 samples)
378{
379 const u8 * data = (const u8*)src;
380 u32 out[2];
381 const int nblocks = len / 8;
382 u32 Step = (len / 4);
383 if(samples == 0) samples = max(Step, 1u);
384 Step = Step / samples;
385 if(Step < 1) Step = 1;
386
387 u32 h1 = 0x8de1c3ac;
388 u32 h2 = 0xbab98226;
389
390 u32 c1 = 0x95543787;
391 u32 c2 = 0x2ad7eb25;
392
393 //----------
394 // body
395
396 const u32 * blocks = (const u32 *)(data + nblocks*8);
397
398 for(int i = -nblocks; i < 0; i+=Step)
399 {
400 u32 k1 = getblock(blocks,i*2+0);
401 u32 k2 = getblock(blocks,i*2+1);
402
403 bmix32(h1,h2,k1,k2,c1,c2);
404 }
405
406 //----------
407 // tail
408
409 const u8 * tail = (const u8*)(data + nblocks*8);
410
411 u32 k1 = 0;
412 u32 k2 = 0;
413
414 switch(len & 7)
415 {
416 case 7: k2 ^= tail[6] << 16;
417 case 6: k2 ^= tail[5] << 8;
418 case 5: k2 ^= tail[4] << 0;
419 case 4: k1 ^= tail[3] << 24;
420 case 3: k1 ^= tail[2] << 16;
421 case 2: k1 ^= tail[1] << 8;
422 case 1: k1 ^= tail[0] << 0;
423 bmix32(h1,h2,k1,k2,c1,c2);
424 };
425
426 //----------
427 // finalization
428
429 h2 ^= len;
430
431 h1 += h2;
432 h2 += h1;
433
434 h1 = fmix32(h1);
435 h2 = fmix32(h2);
436
437 h1 += h2;
438 h2 += h1;
439
440 out[0] = h1;
441 out[1] = h2;
442
443 return *((u64 *)&out);
444}
445
446/*
447 * FIXME: The old 32-bit version of this hash made different hashes than the
448 * 64-bit version. Until someone can make a new version of the 32-bit one that
449 * makes identical hashes, this is just a c/p of the 64-bit one.
450 */
451u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
452{
453 const u64 m = 0xc6a4a7935bd1e995ULL;
454 u64 h = len * m;
455 const int r = 47;
456 u32 Step = (len / 8);
457 const u64 *data = (const u64 *)src;
458 const u64 *end = data + Step;
459 if(samples == 0) samples = max(Step, 1u);
460 Step = Step / samples;
461 if(Step < 1) Step = 1;
462 while(data < end)
463 {
464 u64 k = data[0];
465 data+=Step;
466 k *= m;
467 k ^= k >> r;
468 k *= m;
469 h ^= k;
470 h *= m;
471 }
472
473 const u8 * data2 = (const u8*)end;
474
475 switch(len & 7)
476 {
477 case 7: h ^= u64(data2[6]) << 48;
478 case 6: h ^= u64(data2[5]) << 40;
479 case 5: h ^= u64(data2[4]) << 32;
480 case 4: h ^= u64(data2[3]) << 24;
481 case 3: h ^= u64(data2[2]) << 16;
482 case 2: h ^= u64(data2[1]) << 8;
483 case 1: h ^= u64(data2[0]);
484 h *= m;
485 };
486
487 h ^= h >> r;
488 h *= m;
489 h ^= h >> r;
490
491 return h;
492}
493#endif
494
495u64 GetHash64(const u8 *src, int len, u32 samples)
496{
497 return ptrHashFunction(src, len, samples);
498}
499
500// sets the hash function used for the texture cache
501void SetHash64Function(bool useHiresTextures)
502{
503 if (useHiresTextures)
504 {
505 ptrHashFunction = &GetHashHiresTexture;
506 }
507#if _M_SSE >= 0x402
508 else if (cpu_info.bSSE4_2 && !useHiresTextures) // sse crc32 version
509 {
510 ptrHashFunction = &GetCRC32;
511 }
512#endif
513 else
514 {
515 ptrHashFunction = &GetMurmurHash3;
516 }
517}
518
519
520
diff --git a/src/common/src/hash.h b/src/common/src/hash.h
new file mode 100644
index 000000000..addfa4b5f
--- /dev/null
+++ b/src/common/src/hash.h
@@ -0,0 +1,20 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _HASH_H_
7#define _HASH_H_
8
9#include "common.h"
10
11u32 HashFletcher(const u8* data_u8, size_t length); // FAST. Length & 1 == 0.
12u32 HashAdler32(const u8* data, size_t len); // Fairly accurate, slightly slower
13u32 HashFNV(const u8* ptr, int length); // Another fast and decent hash
14u32 HashEctor(const u8* ptr, int length); // JUNK. DO NOT USE FOR NEW THINGS
15u64 GetCRC32(const u8 *src, int len, u32 samples); // SSE4.2 version of CRC32
16u64 GetHashHiresTexture(const u8 *src, int len, u32 samples);
17u64 GetMurmurHash3(const u8 *src, int len, u32 samples);
18u64 GetHash64(const u8 *src, int len, u32 samples);
19void SetHash64Function(bool useHiresTextures);
20#endif // _HASH_H_
diff --git a/src/common/src/linear_disk_cache.h b/src/common/src/linear_disk_cache.h
new file mode 100644
index 000000000..d33ee7820
--- /dev/null
+++ b/src/common/src/linear_disk_cache.h
@@ -0,0 +1,191 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _LINEAR_DISKCACHE
7#define _LINEAR_DISKCACHE
8
9#include "common.h"
10#include <fstream>
11
12// defined in Version.cpp
13extern const char *scm_rev_git_str;
14
15// On disk format:
16//header{
17// u32 'DCAC';
18// u32 version; // svn_rev
19// u16 sizeof(key_type);
20// u16 sizeof(value_type);
21//}
22
23//key_value_pair{
24// u32 value_size;
25// key_type key;
26// value_type[value_size] value;
27//}
28
29template <typename K, typename V>
30class LinearDiskCacheReader
31{
32public:
33 virtual void Read(const K &key, const V *value, u32 value_size) = 0;
34};
35
36// Dead simple unsorted key-value store with append functionality.
37// No random read functionality, all reading is done in OpenAndRead.
38// Keys and values can contain any characters, including \0.
39//
40// Suitable for caching generated shader bytecode between executions.
41// Not tuned for extreme performance but should be reasonably fast.
42// Does not support keys or values larger than 2GB, which should be reasonable.
43// Keys must have non-zero length; values can have zero length.
44
45// K and V are some POD type
46// K : the key type
47// V : value array type
48template <typename K, typename V>
49class LinearDiskCache
50{
51public:
52 // return number of read entries
53 u32 OpenAndRead(const char *filename, LinearDiskCacheReader<K, V> &reader)
54 {
55 using std::ios_base;
56
57 // close any currently opened file
58 Close();
59 m_num_entries = 0;
60
61 // try opening for reading/writing
62 OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
63
64 m_file.seekg(0, std::ios::end);
65 std::fstream::pos_type end_pos = m_file.tellg();
66 m_file.seekg(0, std::ios::beg);
67 std::fstream::pos_type start_pos = m_file.tellg();
68 std::streamoff file_size = end_pos - start_pos;
69
70 if (m_file.is_open() && ValidateHeader())
71 {
72 // good header, read some key/value pairs
73 K key;
74
75 V *value = NULL;
76 u32 value_size;
77 u32 entry_number;
78
79 std::fstream::pos_type last_pos = m_file.tellg();
80
81 while (Read(&value_size))
82 {
83 std::streamoff next_extent = (last_pos - start_pos) + sizeof(value_size) + value_size;
84 if (next_extent > file_size)
85 break;
86
87 delete[] value;
88 value = new V[value_size];
89
90 // read key/value and pass to reader
91 if (Read(&key) &&
92 Read(value, value_size) &&
93 Read(&entry_number) &&
94 entry_number == m_num_entries+1)
95 {
96 reader.Read(key, value, value_size);
97 }
98 else
99 {
100 break;
101 }
102
103 m_num_entries++;
104 last_pos = m_file.tellg();
105 }
106 m_file.seekp(last_pos);
107 m_file.clear();
108
109 delete[] value;
110 return m_num_entries;
111 }
112
113 // failed to open file for reading or bad header
114 // close and recreate file
115 Close();
116 m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
117 WriteHeader();
118 return 0;
119 }
120
121 void Sync()
122 {
123 m_file.flush();
124 }
125
126 void Close()
127 {
128 if (m_file.is_open())
129 m_file.close();
130 // clear any error flags
131 m_file.clear();
132 }
133
134 // Appends a key-value pair to the store.
135 void Append(const K &key, const V *value, u32 value_size)
136 {
137 // TODO: Should do a check that we don't already have "key"? (I think each caller does that already.)
138 Write(&value_size);
139 Write(&key);
140 Write(value, value_size);
141 m_num_entries++;
142 Write(&m_num_entries);
143 }
144
145private:
146 void WriteHeader()
147 {
148 Write(&m_header);
149 }
150
151 bool ValidateHeader()
152 {
153 char file_header[sizeof(Header)];
154
155 return (Read(file_header, sizeof(Header))
156 && !memcmp((const char*)&m_header, file_header, sizeof(Header)));
157 }
158
159 template <typename D>
160 bool Write(const D *data, u32 count = 1)
161 {
162 return m_file.write((const char*)data, count * sizeof(D)).good();
163 }
164
165 template <typename D>
166 bool Read(const D *data, u32 count = 1)
167 {
168 return m_file.read((char*)data, count * sizeof(D)).good();
169 }
170
171 struct Header
172 {
173 Header()
174 : id(*(u32*)"DCAC")
175 , key_t_size(sizeof(K))
176 , value_t_size(sizeof(V))
177 {
178 memcpy(ver, scm_rev_git_str, 40);
179 }
180
181 const u32 id;
182 const u16 key_t_size, value_t_size;
183 char ver[40];
184
185 } m_header;
186
187 std::fstream m_file;
188 u32 m_num_entries;
189};
190
191#endif // _LINEAR_DISKCACHE
diff --git a/src/common/src/log.h b/src/common/src/log.h
new file mode 100644
index 000000000..8691a825f
--- /dev/null
+++ b/src/common/src/log.h
@@ -0,0 +1,155 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _LOG_H_
6#define _LOG_H_
7
8#define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and OSReports.
9#define ERROR_LEVEL 2 // Critical errors
10#define WARNING_LEVEL 3 // Something is suspicious.
11#define INFO_LEVEL 4 // General information.
12#define DEBUG_LEVEL 5 // Detailed debugging - might make things slow.
13
14namespace LogTypes
15{
16
17enum LOG_TYPE {
18 ACTIONREPLAY,
19 AUDIO,
20 AUDIO_INTERFACE,
21 BOOT,
22 COMMANDPROCESSOR,
23 COMMON,
24 CONSOLE,
25 DISCIO,
26 FILEMON,
27 DSPHLE,
28 DSPLLE,
29 DSP_MAIL,
30 DSPINTERFACE,
31 DVDINTERFACE,
32 DYNA_REC,
33 EXPANSIONINTERFACE,
34 GDB_STUB,
35 POWERPC,
36 GPFIFO,
37 OSHLE,
38 MASTER_LOG,
39 MEMMAP,
40 MEMCARD_MANAGER,
41 OSREPORT,
42 PAD,
43 PROCESSORINTERFACE,
44 PIXELENGINE,
45 SERIALINTERFACE,
46 SP1,
47 STREAMINGINTERFACE,
48 VIDEO,
49 VIDEOINTERFACE,
50 WII_IOB,
51 WII_IPC,
52 WII_IPC_DVD,
53 WII_IPC_ES,
54 WII_IPC_FILEIO,
55 WII_IPC_HID,
56 WII_IPC_HLE,
57 WII_IPC_NET,
58 WII_IPC_WC24,
59 WII_IPC_SSL,
60 WII_IPC_SD,
61 WII_IPC_STM,
62 WII_IPC_WIIMOTE,
63 WIIMOTE,
64 NETPLAY,
65
66 NUMBER_OF_LOGS // Must be last
67};
68
69// FIXME: should this be removed?
70enum LOG_LEVELS {
71 LNOTICE = NOTICE_LEVEL,
72 LERROR = ERROR_LEVEL,
73 LWARNING = WARNING_LEVEL,
74 LINFO = INFO_LEVEL,
75 LDEBUG = DEBUG_LEVEL,
76};
77
78#define LOGTYPES_LEVELS LogTypes::LOG_LEVELS
79#define LOGTYPES_TYPE LogTypes::LOG_TYPE
80
81} // namespace
82
83void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
84 const char *file, int line, const char *fmt, ...)
85#ifdef __GNUC__
86 __attribute__((format(printf, 5, 6)))
87#endif
88 ;
89
90#if defined LOGGING || defined _DEBUG || defined DEBUGFAST
91#define MAX_LOGLEVEL DEBUG_LEVEL
92#else
93#ifndef MAX_LOGLEVEL
94#define MAX_LOGLEVEL WARNING_LEVEL
95#endif // loglevel
96#endif // logging
97
98#ifdef GEKKO
99#define GENERIC_LOG(t, v, ...)
100#else
101// Let the compiler optimize this out
102#define GENERIC_LOG(t, v, ...) { \
103 if (v <= MAX_LOGLEVEL) \
104 GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \
105 }
106#endif
107
108#define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (0)
109#define WARN_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LWARNING, __VA_ARGS__) } while (0)
110#define NOTICE_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LNOTICE, __VA_ARGS__) } while (0)
111#define INFO_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LINFO, __VA_ARGS__) } while (0)
112#define DEBUG_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LDEBUG, __VA_ARGS__) } while (0)
113
114#if MAX_LOGLEVEL >= DEBUG_LEVEL
115#define _dbg_assert_(_t_, _a_) \
116 if (!(_a_)) {\
117 ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \
118 __LINE__, __FILE__, __TIME__); \
119 if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \
120 }
121#define _dbg_assert_msg_(_t_, _a_, ...)\
122 if (!(_a_)) {\
123 ERROR_LOG(_t_, __VA_ARGS__); \
124 if (!PanicYesNo(__VA_ARGS__)) {Crash();} \
125 }
126#define _dbg_update_() Host_UpdateLogDisplay();
127
128#else // not debug
129#define _dbg_update_() ;
130
131#ifndef _dbg_assert_
132#define _dbg_assert_(_t_, _a_) {}
133#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) {}
134#endif // dbg_assert
135#endif // MAX_LOGLEVEL DEBUG
136
137#define _assert_(_a_) _dbg_assert_(MASTER_LOG, _a_)
138
139#ifndef GEKKO
140#ifdef _WIN32
141#define _assert_msg_(_t_, _a_, _fmt_, ...) \
142 if (!(_a_)) {\
143 if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \
144 }
145#else // not win32
146#define _assert_msg_(_t_, _a_, _fmt_, ...) \
147 if (!(_a_)) {\
148 if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \
149 }
150#endif // WIN32
151#else // GEKKO
152#define _assert_msg_(_t_, _a_, _fmt_, ...)
153#endif
154
155#endif // _LOG_H_
diff --git a/src/common/src/log_manager.cpp b/src/common/src/log_manager.cpp
new file mode 100644
index 000000000..c19f728f8
--- /dev/null
+++ b/src/common/src/log_manager.cpp
@@ -0,0 +1,199 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <algorithm>
6
7#ifdef ANDROID
8#include "Host.h"
9#endif
10#include "log_manager.h"
11#include "console_listener.h"
12#include "timer.h"
13#include "thread.h"
14#include "file_util.h"
15
16void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
17 const char *file, int line, const char* fmt, ...)
18{
19 va_list args;
20 va_start(args, fmt);
21 if (LogManager::GetInstance())
22 LogManager::GetInstance()->Log(level, type,
23 file, line, fmt, args);
24 va_end(args);
25}
26
27LogManager *LogManager::m_logManager = NULL;
28
29LogManager::LogManager()
30{
31 // create log files
32 m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
33 m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
34 m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
35 m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
36 m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
37 m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
38 m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
39 m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
40 m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
41 m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt");
42 m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt");
43 m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap");
44 m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1");
45 m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt");
46 m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface");
47 m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface");
48 m_Log[LogTypes::GPFIFO] = new LogContainer("GP", "GPFifo");
49 m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt");
50 m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub");
51 m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
52 m_Log[LogTypes::POWERPC] = new LogContainer("PowerPC", "IBM CPU");
53 m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
54 m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
55 m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
56 m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
57 m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
58 m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
59 m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler");
60 m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
61 m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
62 m_Log[LogTypes::WIIMOTE] = new LogContainer("Wiimote", "Wiimote");
63 m_Log[LogTypes::WII_IOB] = new LogContainer("WII_IOB", "WII IO Bridge");
64 m_Log[LogTypes::WII_IPC] = new LogContainer("WII_IPC", "WII IPC");
65 m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
66 m_Log[LogTypes::WII_IPC_HLE] = new LogContainer("WII_IPC_HLE", "WII IPC HLE");
67 m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD");
68 m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES");
69 m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO","WII IPC FILEIO");
70 m_Log[LogTypes::WII_IPC_SD] = new LogContainer("WII_IPC_SD", "WII IPC SD");
71 m_Log[LogTypes::WII_IPC_STM] = new LogContainer("WII_IPC_STM", "WII IPC STM");
72 m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET");
73 m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
74 m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
75 m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE");
76 m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
77 m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
78 m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
79
80 m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
81 m_consoleLog = new ConsoleListener();
82 m_debuggerLog = new DebuggerLogListener();
83
84 for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
85 {
86 m_Log[i]->SetEnable(true);
87 m_Log[i]->AddListener(m_fileLog);
88 m_Log[i]->AddListener(m_consoleLog);
89#ifdef _MSC_VER
90 if (IsDebuggerPresent())
91 m_Log[i]->AddListener(m_debuggerLog);
92#endif
93 }
94}
95
96LogManager::~LogManager()
97{
98 for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
99 {
100 m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
101 m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
102 m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog);
103 }
104
105 for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
106 delete m_Log[i];
107
108 delete m_fileLog;
109 delete m_consoleLog;
110 delete m_debuggerLog;
111}
112
113void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
114 const char *file, int line, const char *format, va_list args)
115{
116 char temp[MAX_MSGLEN];
117 char msg[MAX_MSGLEN * 2];
118 LogContainer *log = m_Log[type];
119
120 if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners())
121 return;
122
123 CharArrayFromFormatV(temp, MAX_MSGLEN, format, args);
124
125 static const char level_to_char[7] = "-NEWID";
126 sprintf(msg, "%s %s:%u %c[%s]: %s\n",
127 Common::Timer::GetTimeFormatted().c_str(),
128 file, line, level_to_char[(int)level],
129 log->GetShortName(), temp);
130#ifdef ANDROID
131 Host_SysMessage(msg);
132#endif
133 log->Trigger(level, msg);
134}
135
136void LogManager::Init()
137{
138 m_logManager = new LogManager();
139}
140
141void LogManager::Shutdown()
142{
143 delete m_logManager;
144 m_logManager = NULL;
145}
146
147LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable)
148 : m_enable(enable)
149{
150 strncpy(m_fullName, fullName, 128);
151 strncpy(m_shortName, shortName, 32);
152 m_level = LogTypes::LWARNING;
153}
154
155// LogContainer
156void LogContainer::AddListener(LogListener *listener)
157{
158 std::lock_guard<std::mutex> lk(m_listeners_lock);
159 m_listeners.insert(listener);
160}
161
162void LogContainer::RemoveListener(LogListener *listener)
163{
164 std::lock_guard<std::mutex> lk(m_listeners_lock);
165 m_listeners.erase(listener);
166}
167
168void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
169{
170 std::lock_guard<std::mutex> lk(m_listeners_lock);
171
172 std::set<LogListener*>::const_iterator i;
173 for (i = m_listeners.begin(); i != m_listeners.end(); ++i)
174 {
175 (*i)->Log(level, msg);
176 }
177}
178
179FileLogListener::FileLogListener(const char *filename)
180{
181 OpenFStream(m_logfile, filename, std::ios::app);
182 SetEnable(true);
183}
184
185void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
186{
187 if (!IsEnabled() || !IsValid())
188 return;
189
190 std::lock_guard<std::mutex> lk(m_log_lock);
191 m_logfile << msg << std::flush;
192}
193
194void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
195{
196#if _MSC_VER
197 ::OutputDebugStringA(msg);
198#endif
199}
diff --git a/src/common/src/log_manager.h b/src/common/src/log_manager.h
new file mode 100644
index 000000000..59078849b
--- /dev/null
+++ b/src/common/src/log_manager.h
@@ -0,0 +1,169 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _LOGMANAGER_H_
6#define _LOGMANAGER_H_
7
8#include "log.h"
9#include "string_util.h"
10#include "thread.h"
11#include "file_util.h"
12
13#include <set>
14#include <string.h>
15
16#define MAX_MESSAGES 8000
17#define MAX_MSGLEN 1024
18
19
20// pure virtual interface
21class LogListener
22{
23public:
24 virtual ~LogListener() {}
25
26 virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0;
27};
28
29class FileLogListener : public LogListener
30{
31public:
32 FileLogListener(const char *filename);
33
34 void Log(LogTypes::LOG_LEVELS, const char *msg);
35
36 bool IsValid() { return !m_logfile.fail(); }
37 bool IsEnabled() const { return m_enable; }
38 void SetEnable(bool enable) { m_enable = enable; }
39
40 const char* GetName() const { return "file"; }
41
42private:
43 std::mutex m_log_lock;
44 std::ofstream m_logfile;
45 bool m_enable;
46};
47
48class DebuggerLogListener : public LogListener
49{
50public:
51 void Log(LogTypes::LOG_LEVELS, const char *msg);
52};
53
54class LogContainer
55{
56public:
57 LogContainer(const char* shortName, const char* fullName, bool enable = false);
58
59 const char* GetShortName() const { return m_shortName; }
60 const char* GetFullName() const { return m_fullName; }
61
62 void AddListener(LogListener* listener);
63 void RemoveListener(LogListener* listener);
64
65 void Trigger(LogTypes::LOG_LEVELS, const char *msg);
66
67 bool IsEnabled() const { return m_enable; }
68 void SetEnable(bool enable) { m_enable = enable; }
69
70 LogTypes::LOG_LEVELS GetLevel() const { return m_level; }
71
72 void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; }
73
74 bool HasListeners() const { return !m_listeners.empty(); }
75
76private:
77 char m_fullName[128];
78 char m_shortName[32];
79 bool m_enable;
80 LogTypes::LOG_LEVELS m_level;
81 std::mutex m_listeners_lock;
82 std::set<LogListener*> m_listeners;
83};
84
85class ConsoleListener;
86
87class LogManager : NonCopyable
88{
89private:
90 LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
91 FileLogListener *m_fileLog;
92 ConsoleListener *m_consoleLog;
93 DebuggerLogListener *m_debuggerLog;
94 static LogManager *m_logManager; // Singleton. Ugh.
95
96 LogManager();
97 ~LogManager();
98public:
99
100 static u32 GetMaxLevel() { return MAX_LOGLEVEL; }
101
102 void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
103 const char *file, int line, const char *fmt, va_list args);
104
105 void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level)
106 {
107 m_Log[type]->SetLevel(level);
108 }
109
110 void SetEnable(LogTypes::LOG_TYPE type, bool enable)
111 {
112 m_Log[type]->SetEnable(enable);
113 }
114
115 bool IsEnabled(LogTypes::LOG_TYPE type) const
116 {
117 return m_Log[type]->IsEnabled();
118 }
119
120 const char* GetShortName(LogTypes::LOG_TYPE type) const
121 {
122 return m_Log[type]->GetShortName();
123 }
124
125 const char* GetFullName(LogTypes::LOG_TYPE type) const
126 {
127 return m_Log[type]->GetFullName();
128 }
129
130 void AddListener(LogTypes::LOG_TYPE type, LogListener *listener)
131 {
132 m_Log[type]->AddListener(listener);
133 }
134
135 void RemoveListener(LogTypes::LOG_TYPE type, LogListener *listener)
136 {
137 m_Log[type]->RemoveListener(listener);
138 }
139
140 FileLogListener *GetFileListener() const
141 {
142 return m_fileLog;
143 }
144
145 ConsoleListener *GetConsoleListener() const
146 {
147 return m_consoleLog;
148 }
149
150 DebuggerLogListener *GetDebuggerListener() const
151 {
152 return m_debuggerLog;
153 }
154
155 static LogManager* GetInstance()
156 {
157 return m_logManager;
158 }
159
160 static void SetInstance(LogManager *logManager)
161 {
162 m_logManager = logManager;
163 }
164
165 static void Init();
166 static void Shutdown();
167};
168
169#endif // _LOGMANAGER_H_
diff --git a/src/common/src/math_util.cpp b/src/common/src/math_util.cpp
new file mode 100644
index 000000000..6667e078c
--- /dev/null
+++ b/src/common/src/math_util.cpp
@@ -0,0 +1,212 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#include "common.h"
7#include "math_util.h"
8
9#include <cmath>
10#include <numeric>
11
12namespace MathUtil
13{
14
15u32 ClassifyDouble(double dvalue)
16{
17 // TODO: Optimize the below to be as fast as possible.
18 IntDouble value;
19 value.d = dvalue;
20 u64 sign = value.i & DOUBLE_SIGN;
21 u64 exp = value.i & DOUBLE_EXP;
22 if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
23 {
24 // Nice normalized number.
25 return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
26 }
27 else
28 {
29 u64 mantissa = value.i & DOUBLE_FRAC;
30 if (mantissa)
31 {
32 if (exp)
33 {
34 return PPC_FPCLASS_QNAN;
35 }
36 else
37 {
38 // Denormalized number.
39 return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
40 }
41 }
42 else if (exp)
43 {
44 //Infinite
45 return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
46 }
47 else
48 {
49 //Zero
50 return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
51 }
52 }
53}
54
55u32 ClassifyFloat(float fvalue)
56{
57 // TODO: Optimize the below to be as fast as possible.
58 IntFloat value;
59 value.f = fvalue;
60 u32 sign = value.i & FLOAT_SIGN;
61 u32 exp = value.i & FLOAT_EXP;
62 if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
63 {
64 // Nice normalized number.
65 return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
66 }
67 else
68 {
69 u32 mantissa = value.i & FLOAT_FRAC;
70 if (mantissa)
71 {
72 if (exp)
73 {
74 return PPC_FPCLASS_QNAN; // Quiet NAN
75 }
76 else
77 {
78 // Denormalized number.
79 return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
80 }
81 }
82 else if (exp)
83 {
84 // Infinite
85 return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
86 }
87 else
88 {
89 //Zero
90 return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
91 }
92 }
93}
94
95
96} // namespace
97
98inline void MatrixMul(int n, const float *a, const float *b, float *result)
99{
100 for (int i = 0; i < n; ++i)
101 {
102 for (int j = 0; j < n; ++j)
103 {
104 float temp = 0;
105 for (int k = 0; k < n; ++k)
106 {
107 temp += a[i * n + k] * b[k * n + j];
108 }
109 result[i * n + j] = temp;
110 }
111 }
112}
113
114// Calculate sum of a float list
115float MathFloatVectorSum(const std::vector<float>& Vec)
116{
117 return std::accumulate(Vec.begin(), Vec.end(), 0.0f);
118}
119
120void Matrix33::LoadIdentity(Matrix33 &mtx)
121{
122 memset(mtx.data, 0, sizeof(mtx.data));
123 mtx.data[0] = 1.0f;
124 mtx.data[4] = 1.0f;
125 mtx.data[8] = 1.0f;
126}
127
128void Matrix33::RotateX(Matrix33 &mtx, float rad)
129{
130 float s = sin(rad);
131 float c = cos(rad);
132 memset(mtx.data, 0, sizeof(mtx.data));
133 mtx.data[0] = 1;
134 mtx.data[4] = c;
135 mtx.data[5] = -s;
136 mtx.data[7] = s;
137 mtx.data[8] = c;
138}
139void Matrix33::RotateY(Matrix33 &mtx, float rad)
140{
141 float s = sin(rad);
142 float c = cos(rad);
143 memset(mtx.data, 0, sizeof(mtx.data));
144 mtx.data[0] = c;
145 mtx.data[2] = s;
146 mtx.data[4] = 1;
147 mtx.data[6] = -s;
148 mtx.data[8] = c;
149}
150
151void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result)
152{
153 MatrixMul(3, a.data, b.data, result.data);
154}
155
156void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3])
157{
158 for (int i = 0; i < 3; ++i) {
159 result[i] = 0;
160 for (int k = 0; k < 3; ++k) {
161 result[i] += a.data[i * 3 + k] * vec[k];
162 }
163 }
164}
165
166void Matrix44::LoadIdentity(Matrix44 &mtx)
167{
168 memset(mtx.data, 0, sizeof(mtx.data));
169 mtx.data[0] = 1.0f;
170 mtx.data[5] = 1.0f;
171 mtx.data[10] = 1.0f;
172 mtx.data[15] = 1.0f;
173}
174
175void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33)
176{
177 for (int i = 0; i < 3; ++i)
178 {
179 for (int j = 0; j < 3; ++j)
180 {
181 mtx.data[i * 4 + j] = m33.data[i * 3 + j];
182 }
183 }
184
185 for (int i = 0; i < 3; ++i)
186 {
187 mtx.data[i * 4 + 3] = 0;
188 mtx.data[i + 12] = 0;
189 }
190 mtx.data[15] = 1.0f;
191}
192
193void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16])
194{
195 for(int i = 0; i < 16; ++i) {
196 mtx.data[i] = mtxArray[i];
197 }
198}
199
200void Matrix44::Translate(Matrix44 &mtx, const float vec[3])
201{
202 LoadIdentity(mtx);
203 mtx.data[3] = vec[0];
204 mtx.data[7] = vec[1];
205 mtx.data[11] = vec[2];
206}
207
208void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result)
209{
210 MatrixMul(4, a.data, b.data, result.data);
211}
212
diff --git a/src/common/src/math_util.h b/src/common/src/math_util.h
new file mode 100644
index 000000000..4dd12c309
--- /dev/null
+++ b/src/common/src/math_util.h
@@ -0,0 +1,200 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _MATH_UTIL_H_
7#define _MATH_UTIL_H_
8
9#include "common.h"
10
11#include <vector>
12
13namespace MathUtil
14{
15
16static const u64 DOUBLE_SIGN = 0x8000000000000000ULL,
17 DOUBLE_EXP = 0x7FF0000000000000ULL,
18 DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL,
19 DOUBLE_ZERO = 0x0000000000000000ULL;
20
21static const u32 FLOAT_SIGN = 0x80000000,
22 FLOAT_EXP = 0x7F800000,
23 FLOAT_FRAC = 0x007FFFFF,
24 FLOAT_ZERO = 0x00000000;
25
26union IntDouble {
27 double d;
28 u64 i;
29};
30union IntFloat {
31 float f;
32 u32 i;
33};
34
35inline bool IsNAN(double d)
36{
37 IntDouble x; x.d = d;
38 return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
39 ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) );
40}
41
42inline bool IsQNAN(double d)
43{
44 IntDouble x; x.d = d;
45 return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
46 ((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) &&
47 ((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) );
48}
49
50inline bool IsSNAN(double d)
51{
52 IntDouble x; x.d = d;
53 return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
54 ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) &&
55 ((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) );
56}
57
58inline float FlushToZero(float f)
59{
60 IntFloat x; x.f = f;
61 if ((x.i & FLOAT_EXP) == 0)
62 x.i &= FLOAT_SIGN; // turn into signed zero
63 return x.f;
64}
65
66inline double FlushToZeroAsFloat(double d)
67{
68 IntDouble x; x.d = d;
69 if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL)
70 x.i &= DOUBLE_SIGN; // turn into signed zero
71 return x.d;
72}
73
74enum PPCFpClass
75{
76 PPC_FPCLASS_QNAN = 0x11,
77 PPC_FPCLASS_NINF = 0x9,
78 PPC_FPCLASS_NN = 0x8,
79 PPC_FPCLASS_ND = 0x18,
80 PPC_FPCLASS_NZ = 0x12,
81 PPC_FPCLASS_PZ = 0x2,
82 PPC_FPCLASS_PD = 0x14,
83 PPC_FPCLASS_PN = 0x4,
84 PPC_FPCLASS_PINF = 0x5,
85};
86
87// Uses PowerPC conventions for the return value, so it can be easily
88// used directly in CPU emulation.
89u32 ClassifyDouble(double dvalue);
90// More efficient float version.
91u32 ClassifyFloat(float fvalue);
92
93template<class T>
94struct Rectangle
95{
96 T left;
97 T top;
98 T right;
99 T bottom;
100
101 Rectangle()
102 { }
103
104 Rectangle(T theLeft, T theTop, T theRight, T theBottom)
105 : left(theLeft), top(theTop), right(theRight), bottom(theBottom)
106 { }
107
108 bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
109
110 T GetWidth() const { return abs(right - left); }
111 T GetHeight() const { return abs(bottom - top); }
112
113 // If the rectangle is in a coordinate system with a lower-left origin, use
114 // this Clamp.
115 void ClampLL(T x1, T y1, T x2, T y2)
116 {
117 if (left < x1) left = x1;
118 if (right > x2) right = x2;
119 if (top > y1) top = y1;
120 if (bottom < y2) bottom = y2;
121 }
122
123 // If the rectangle is in a coordinate system with an upper-left origin,
124 // use this Clamp.
125 void ClampUL(T x1, T y1, T x2, T y2)
126 {
127 if (left < x1) left = x1;
128 if (right > x2) right = x2;
129 if (top < y1) top = y1;
130 if (bottom > y2) bottom = y2;
131 }
132};
133
134} // namespace MathUtil
135
136inline float pow2f(float x) {return x * x;}
137inline double pow2(double x) {return x * x;}
138
139float MathFloatVectorSum(const std::vector<float>&);
140
141#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
142#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
143
144// Rounds down. 0 -> undefined
145inline u64 Log2(u64 val)
146{
147#if defined(__GNUC__)
148 return 63 - __builtin_clzll(val);
149
150#elif defined(_MSC_VER) && defined(_M_X64)
151 unsigned long result = -1;
152 _BitScanReverse64(&result, val);
153 return result;
154
155#else
156 u64 result = -1;
157 while (val != 0)
158 {
159 val >>= 1;
160 ++result;
161 }
162 return result;
163#endif
164}
165
166// Tiny matrix/vector library.
167// Used for things like Free-Look in the gfx backend.
168
169class Matrix33
170{
171public:
172 static void LoadIdentity(Matrix33 &mtx);
173
174 // set mtx to be a rotation matrix around the x axis
175 static void RotateX(Matrix33 &mtx, float rad);
176 // set mtx to be a rotation matrix around the y axis
177 static void RotateY(Matrix33 &mtx, float rad);
178
179 // set result = a x b
180 static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
181 static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
182
183 float data[9];
184};
185
186class Matrix44
187{
188public:
189 static void LoadIdentity(Matrix44 &mtx);
190 static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
191 static void Set(Matrix44 &mtx, const float mtxArray[16]);
192
193 static void Translate(Matrix44 &mtx, const float vec[3]);
194
195 static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
196
197 float data[16];
198};
199
200#endif // _MATH_UTIL_H_
diff --git a/src/common/src/mem_arena.cpp b/src/common/src/mem_arena.cpp
new file mode 100644
index 000000000..13cd00fd3
--- /dev/null
+++ b/src/common/src/mem_arena.cpp
@@ -0,0 +1,304 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#include "common.h"
7#include "memory_util.h"
8#include "mem_arena.h"
9
10#ifdef _WIN32
11#include <windows.h>
12#else
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16#include <cerrno>
17#include <cstring>
18#ifdef ANDROID
19#include <sys/ioctl.h>
20#include <linux/ashmem.h>
21#endif
22#endif
23#include <set>
24
25#if defined(__APPLE__)
26static const char* ram_temp_file = "/tmp/gc_mem.tmp";
27#elif !defined(_WIN32) // non OSX unixes
28static const char* ram_temp_file = "/dev/shm/gc_mem.tmp";
29#endif
30#ifdef ANDROID
31#define ASHMEM_DEVICE "/dev/ashmem"
32
33int AshmemCreateFileMapping(const char *name, size_t size)
34{
35 int fd, ret;
36 fd = open(ASHMEM_DEVICE, O_RDWR);
37 if (fd < 0)
38 return fd;
39
40 // We don't really care if we can't set the name, it is optional
41 ret = ioctl(fd, ASHMEM_SET_NAME, name);
42
43 ret = ioctl(fd, ASHMEM_SET_SIZE, size);
44 if (ret < 0)
45 {
46 close(fd);
47 NOTICE_LOG(MEMMAP, "Ashmem returned error: 0x%08x", ret);
48 return ret;
49 }
50 return fd;
51}
52#endif
53
54void MemArena::GrabLowMemSpace(size_t size)
55{
56#ifdef _WIN32
57 hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL);
58#elif defined(ANDROID)
59 fd = AshmemCreateFileMapping("Dolphin-emu", size);
60 if (fd < 0)
61 {
62 NOTICE_LOG(MEMMAP, "Ashmem allocation failed");
63 return;
64 }
65#else
66 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
67 fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);
68 unlink(ram_temp_file);
69 if (ftruncate(fd, size) < 0)
70 ERROR_LOG(MEMMAP, "Failed to allocate low memory space");
71 return;
72#endif
73}
74
75
76void MemArena::ReleaseSpace()
77{
78#ifdef _WIN32
79 CloseHandle(hMemoryMapping);
80 hMemoryMapping = 0;
81#else
82 close(fd);
83#endif
84}
85
86
87void *MemArena::CreateView(s64 offset, size_t size, void *base)
88{
89#ifdef _WIN32
90 return MapViewOfFileEx(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size, base);
91#else
92 void *retval = mmap(
93 base, size,
94 PROT_READ | PROT_WRITE,
95 MAP_SHARED | ((base == nullptr) ? 0 : MAP_FIXED),
96 fd, offset);
97
98 if (retval == MAP_FAILED)
99 {
100 NOTICE_LOG(MEMMAP, "mmap on %s failed", ram_temp_file);
101 return nullptr;
102 }
103 else
104 {
105 return retval;
106 }
107#endif
108}
109
110
111void MemArena::ReleaseView(void* view, size_t size)
112{
113#ifdef _WIN32
114 UnmapViewOfFile(view);
115#else
116 munmap(view, size);
117#endif
118}
119
120
121u8* MemArena::Find4GBBase()
122{
123#ifdef _M_X64
124#ifdef _WIN32
125 // 64 bit
126 u8* base = (u8*)VirtualAlloc(0, 0xE1000000, MEM_RESERVE, PAGE_READWRITE);
127 VirtualFree(base, 0, MEM_RELEASE);
128 return base;
129#else
130 // Very precarious - mmap cannot return an error when trying to map already used pages.
131 // This makes the Windows approach above unusable on Linux, so we will simply pray...
132 return reinterpret_cast<u8*>(0x2300000000ULL);
133#endif
134
135#else
136 // 32 bit
137#ifdef _WIN32
138 // The highest thing in any 1GB section of memory space is the locked cache. We only need to fit it.
139 u8* base = (u8*)VirtualAlloc(0, 0x31000000, MEM_RESERVE, PAGE_READWRITE);
140 if (base) {
141 VirtualFree(base, 0, MEM_RELEASE);
142 }
143 return base;
144#else
145#ifdef ANDROID
146 // Android 4.3 changed how mmap works.
147 // if we map it private and then munmap it, we can't use the base returned.
148 // This may be due to changes in them support a full SELinux implementation.
149 const int flags = MAP_ANON;
150#else
151 const int flags = MAP_ANON | MAP_PRIVATE;
152#endif
153 const u32 MemSize = 0x31000000;
154 void* base = mmap(0, MemSize, PROT_NONE, flags, -1, 0);
155 if (base == MAP_FAILED) {
156 PanicAlert("Failed to map 1 GB of memory space: %s", strerror(errno));
157 return 0;
158 }
159 munmap(base, MemSize);
160 return static_cast<u8*>(base);
161#endif
162#endif
163}
164
165
166// yeah, this could also be done in like two bitwise ops...
167#define SKIP(a_flags, b_flags) \
168 if (!(a_flags & MV_WII_ONLY) && (b_flags & MV_WII_ONLY)) \
169 continue; \
170 if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM)) \
171 continue; \
172
173
174static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) {
175 // OK, we know where to find free space. Now grab it!
176 // We just mimic the popular BAT setup.
177 u32 position = 0;
178 u32 last_position = 0;
179
180 // Zero all the pointers to be sure.
181 for (int i = 0; i < num_views; i++)
182 {
183 if (views[i].out_ptr_low)
184 *views[i].out_ptr_low = 0;
185 if (views[i].out_ptr)
186 *views[i].out_ptr = 0;
187 }
188
189 int i;
190 for (i = 0; i < num_views; i++)
191 {
192 SKIP(flags, views[i].flags);
193 if (views[i].flags & MV_MIRROR_PREVIOUS) {
194 position = last_position;
195 } else {
196 *(views[i].out_ptr_low) = (u8*)arena->CreateView(position, views[i].size);
197 if (!*views[i].out_ptr_low)
198 goto bail;
199 }
200#ifdef _M_X64
201 *views[i].out_ptr = (u8*)arena->CreateView(
202 position, views[i].size, base + views[i].virtual_address);
203#else
204 if (views[i].flags & MV_MIRROR_PREVIOUS) {
205 // No need to create multiple identical views.
206 *views[i].out_ptr = *views[i - 1].out_ptr;
207 } else {
208 *views[i].out_ptr = (u8*)arena->CreateView(
209 position, views[i].size, base + (views[i].virtual_address & 0x3FFFFFFF));
210 if (!*views[i].out_ptr)
211 goto bail;
212 }
213#endif
214 last_position = position;
215 position += views[i].size;
216 }
217
218 return true;
219
220bail:
221 // Argh! ERROR! Free what we grabbed so far so we can try again.
222 MemoryMap_Shutdown(views, i+1, flags, arena);
223 return false;
224}
225
226u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena *arena)
227{
228 u32 total_mem = 0;
229 int base_attempts = 0;
230
231 for (int i = 0; i < num_views; i++)
232 {
233 SKIP(flags, views[i].flags);
234 if ((views[i].flags & MV_MIRROR_PREVIOUS) == 0)
235 total_mem += views[i].size;
236 }
237 // Grab some pagefile backed memory out of the void ...
238 arena->GrabLowMemSpace(total_mem);
239
240 // Now, create views in high memory where there's plenty of space.
241#ifdef _M_X64
242 u8 *base = MemArena::Find4GBBase();
243 // This really shouldn't fail - in 64-bit, there will always be enough
244 // address space.
245 if (!Memory_TryBase(base, views, num_views, flags, arena))
246 {
247 PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
248 exit(0);
249 return 0;
250 }
251#else
252#ifdef _WIN32
253 // Try a whole range of possible bases. Return once we got a valid one.
254 u32 max_base_addr = 0x7FFF0000 - 0x31000000;
255 u8 *base = NULL;
256
257 for (u32 base_addr = 0x40000; base_addr < max_base_addr; base_addr += 0x40000)
258 {
259 base_attempts++;
260 base = (u8 *)base_addr;
261 if (Memory_TryBase(base, views, num_views, flags, arena))
262 {
263 INFO_LOG(MEMMAP, "Found valid memory base at %p after %i tries.", base, base_attempts);
264 base_attempts = 0;
265 break;
266 }
267
268 }
269#else
270 // Linux32 is fine with the x64 method, although limited to 32-bit with no automirrors.
271 u8 *base = MemArena::Find4GBBase();
272 if (!Memory_TryBase(base, views, num_views, flags, arena))
273 {
274 PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
275 exit(0);
276 return 0;
277 }
278#endif
279
280#endif
281 if (base_attempts)
282 PanicAlert("No possible memory base pointer found!");
283 return base;
284}
285
286void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemArena *arena)
287{
288 std::set<void*> freeset;
289 for (int i = 0; i < num_views; i++)
290 {
291 const MemoryView* view = &views[i];
292 u8** outptrs[2] = {view->out_ptr_low, view->out_ptr};
293 for (int j = 0; j < 2; j++)
294 {
295 u8** outptr = outptrs[j];
296 if (outptr && *outptr && !freeset.count(*outptr))
297 {
298 arena->ReleaseView(*outptr, view->size);
299 freeset.insert(*outptr);
300 *outptr = NULL;
301 }
302 }
303 }
304}
diff --git a/src/common/src/mem_arena.h b/src/common/src/mem_arena.h
new file mode 100644
index 000000000..4c3ded0df
--- /dev/null
+++ b/src/common/src/mem_arena.h
@@ -0,0 +1,58 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _MEMARENA_H_
7#define _MEMARENA_H_
8
9#ifdef _WIN32
10#include <windows.h>
11#endif
12
13#include "common.h"
14
15// This class lets you create a block of anonymous RAM, and then arbitrarily map views into it.
16// Multiple views can mirror the same section of the block, which makes it very convenient for emulating
17// memory mirrors.
18
19class MemArena
20{
21public:
22 void GrabLowMemSpace(size_t size);
23 void ReleaseSpace();
24 void *CreateView(s64 offset, size_t size, void *base = nullptr);
25 void ReleaseView(void *view, size_t size);
26
27 // This only finds 1 GB in 32-bit
28 static u8 *Find4GBBase();
29private:
30
31#ifdef _WIN32
32 HANDLE hMemoryMapping;
33#else
34 int fd;
35#endif
36};
37
38enum {
39 MV_MIRROR_PREVIOUS = 1,
40 MV_FAKE_VMEM = 2,
41 MV_WII_ONLY = 4,
42};
43
44struct MemoryView
45{
46 u8 **out_ptr_low;
47 u8 **out_ptr;
48 u32 virtual_address;
49 u32 size;
50 u32 flags;
51};
52
53// Uses a memory arena to set up an emulator-friendly memory map according to
54// a passed-in list of MemoryView structures.
55u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena *arena);
56void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemArena *arena);
57
58#endif // _MEMARENA_H_
diff --git a/src/common/src/memory_util.cpp b/src/common/src/memory_util.cpp
new file mode 100644
index 000000000..346d2e525
--- /dev/null
+++ b/src/common/src/memory_util.cpp
@@ -0,0 +1,197 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#include "common.h"
7#include "memory_util.h"
8#include "string_util.h"
9
10#ifdef _WIN32
11#include <windows.h>
12#include <psapi.h>
13#else
14#include <errno.h>
15#include <stdio.h>
16#endif
17
18#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
19#include <unistd.h>
20#define PAGE_MASK (getpagesize() - 1)
21#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK))
22#endif
23
24// This is purposely not a full wrapper for virtualalloc/mmap, but it
25// provides exactly the primitive operations that Dolphin needs.
26
27void* AllocateExecutableMemory(size_t size, bool low)
28{
29#if defined(_WIN32)
30 void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
31#else
32 static char *map_hint = 0;
33#if defined(__x86_64__) && !defined(MAP_32BIT)
34 // This OS has no flag to enforce allocation below the 4 GB boundary,
35 // but if we hint that we want a low address it is very likely we will
36 // get one.
37 // An older version of this code used MAP_FIXED, but that has the side
38 // effect of discarding already mapped pages that happen to be in the
39 // requested virtual memory range (such as the emulated RAM, sometimes).
40 if (low && (!map_hint))
41 map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */
42#endif
43 void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC,
44 MAP_ANON | MAP_PRIVATE
45#if defined(__x86_64__) && defined(MAP_32BIT)
46 | (low ? MAP_32BIT : 0)
47#endif
48 , -1, 0);
49#endif /* defined(_WIN32) */
50
51 // printf("Mapped executable memory at %p (size %ld)\n", ptr,
52 // (unsigned long)size);
53
54#if defined(__FreeBSD__)
55 if (ptr == MAP_FAILED)
56 {
57 ptr = NULL;
58#else
59 if (ptr == NULL)
60 {
61#endif
62 PanicAlert("Failed to allocate executable memory");
63 }
64#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
65 else
66 {
67 if (low)
68 {
69 map_hint += size;
70 map_hint = (char*)round_page(map_hint); /* round up to the next page */
71 // printf("Next map will (hopefully) be at %p\n", map_hint);
72 }
73 }
74#endif
75
76#if defined(_M_X64)
77 if ((u64)ptr >= 0x80000000 && low == true)
78 PanicAlert("Executable memory ended up above 2GB!");
79#endif
80
81 return ptr;
82}
83
84void* AllocateMemoryPages(size_t size)
85{
86#ifdef _WIN32
87 void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
88#else
89 void* ptr = mmap(0, size, PROT_READ | PROT_WRITE,
90 MAP_ANON | MAP_PRIVATE, -1, 0);
91#endif
92
93 // printf("Mapped memory at %p (size %ld)\n", ptr,
94 // (unsigned long)size);
95
96 if (ptr == NULL)
97 PanicAlert("Failed to allocate raw memory");
98
99 return ptr;
100}
101
102void* AllocateAlignedMemory(size_t size,size_t alignment)
103{
104#ifdef _WIN32
105 void* ptr = _aligned_malloc(size,alignment);
106#else
107 void* ptr = NULL;
108#ifdef ANDROID
109 ptr = memalign(alignment, size);
110#else
111 if (posix_memalign(&ptr, alignment, size) != 0)
112 ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
113#endif
114#endif
115
116 // printf("Mapped memory at %p (size %ld)\n", ptr,
117 // (unsigned long)size);
118
119 if (ptr == NULL)
120 PanicAlert("Failed to allocate aligned memory");
121
122 return ptr;
123}
124
125void FreeMemoryPages(void* ptr, size_t size)
126{
127 if (ptr)
128 {
129#ifdef _WIN32
130
131 if (!VirtualFree(ptr, 0, MEM_RELEASE))
132 PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
133 ptr = NULL; // Is this our responsibility?
134
135#else
136 munmap(ptr, size);
137#endif
138 }
139}
140
141void FreeAlignedMemory(void* ptr)
142{
143 if (ptr)
144 {
145#ifdef _WIN32
146 _aligned_free(ptr);
147#else
148 free(ptr);
149#endif
150 }
151}
152
153void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
154{
155#ifdef _WIN32
156 DWORD oldValue;
157 if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
158 PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg());
159#else
160 mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
161#endif
162}
163
164void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
165{
166#ifdef _WIN32
167 DWORD oldValue;
168 if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue))
169 PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg());
170#else
171 mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
172#endif
173}
174
175std::string MemUsage()
176{
177#ifdef _WIN32
178#pragma comment(lib, "psapi")
179 DWORD processID = GetCurrentProcessId();
180 HANDLE hProcess;
181 PROCESS_MEMORY_COUNTERS pmc;
182 std::string Ret;
183
184 // Print information about the memory usage of the process.
185
186 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
187 if (NULL == hProcess) return "MemUsage Error";
188
189 if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
190 Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
191
192 CloseHandle(hProcess);
193 return Ret;
194#else
195 return "";
196#endif
197}
diff --git a/src/common/src/memory_util.h b/src/common/src/memory_util.h
new file mode 100644
index 000000000..49b2589da
--- /dev/null
+++ b/src/common/src/memory_util.h
@@ -0,0 +1,25 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#ifndef _MEMORYUTIL_H
7#define _MEMORYUTIL_H
8
9#ifndef _WIN32
10#include <sys/mman.h>
11#endif
12#include <string>
13
14void* AllocateExecutableMemory(size_t size, bool low = true);
15void* AllocateMemoryPages(size_t size);
16void FreeMemoryPages(void* ptr, size_t size);
17void* AllocateAlignedMemory(size_t size,size_t alignment);
18void FreeAlignedMemory(void* ptr);
19void WriteProtectMemory(void* ptr, size_t size, bool executable = false);
20void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute = false);
21std::string MemUsage();
22
23inline int GetPageSize() { return 4096; }
24
25#endif
diff --git a/src/common/src/misc.cpp b/src/common/src/misc.cpp
new file mode 100644
index 000000000..719a98cb9
--- /dev/null
+++ b/src/common/src/misc.cpp
@@ -0,0 +1,33 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common.h"
6
7// Neither Android nor OS X support TLS
8#if defined(__APPLE__) || (ANDROID && __clang__)
9#define __thread
10#endif
11
12// Generic function to get last error message.
13// Call directly after the command or use the error num.
14// This function might change the error code.
15//const char* GetLastErrorMsg()
16//{
17// static const size_t buff_size = 255;
18//
19//#ifdef _WIN32
20// static __declspec(thread) char err_str[buff_size] = {};
21//
22// FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
23// MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
24// err_str, buff_size, NULL);
25//#else
26// static __thread char err_str[buff_size] = {};
27//
28// // Thread safe (XSI-compliant)
29// strerror_r(errno, err_str, buff_size);
30//#endif
31//
32// return err_str;
33//}
diff --git a/src/common/src/msg_handler.cpp b/src/common/src/msg_handler.cpp
new file mode 100644
index 000000000..62cbe0aa7
--- /dev/null
+++ b/src/common/src/msg_handler.cpp
@@ -0,0 +1,107 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <stdio.h> // System
6
7#include "common.h" // Local
8#include "string_util.h"
9
10bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style);
11static MsgAlertHandler msg_handler = DefaultMsgHandler;
12static bool AlertEnabled = true;
13
14std::string DefaultStringTranslator(const char* text);
15static StringTranslator str_translator = DefaultStringTranslator;
16
17// Select which of these functions that are used for message boxes. If
18// wxWidgets is enabled we will use wxMsgAlert() that is defined in Main.cpp
19void RegisterMsgAlertHandler(MsgAlertHandler handler)
20{
21 msg_handler = handler;
22}
23
24// Select translation function. For wxWidgets use wxStringTranslator in Main.cpp
25void RegisterStringTranslator(StringTranslator translator)
26{
27 str_translator = translator;
28}
29
30// enable/disable the alert handler
31void SetEnableAlert(bool enable)
32{
33 AlertEnabled = enable;
34}
35
36// This is the first stop for gui alerts where the log is updated and the
37// correct window is shown
38bool MsgAlert(bool yes_no, int Style, const char* format, ...)
39{
40 // Read message and write it to the log
41 std::string caption;
42 char buffer[2048];
43
44 static std::string info_caption;
45 static std::string warn_caption;
46 static std::string ques_caption;
47 static std::string crit_caption;
48
49 if (!info_caption.length())
50 {
51 info_caption = str_translator(_trans("Information"));
52 ques_caption = str_translator(_trans("Question"));
53 warn_caption = str_translator(_trans("Warning"));
54 crit_caption = str_translator(_trans("Critical"));
55 }
56
57 switch(Style)
58 {
59 case INFORMATION:
60 caption = info_caption;
61 break;
62 case QUESTION:
63 caption = ques_caption;
64 break;
65 case WARNING:
66 caption = warn_caption;
67 break;
68 case CRITICAL:
69 caption = crit_caption;
70 break;
71 }
72
73 va_list args;
74 va_start(args, format);
75 CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args);
76 va_end(args);
77
78 ERROR_LOG(MASTER_LOG, "%s: %s", caption.c_str(), buffer);
79
80 // Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
81 if (msg_handler && (AlertEnabled || Style == QUESTION || Style == CRITICAL))
82 return msg_handler(caption.c_str(), buffer, yes_no, Style);
83
84 return true;
85}
86
87// Default non library dependent panic alert
88bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
89{
90//#ifdef _WIN32
91// int STYLE = MB_ICONINFORMATION;
92// if (Style == QUESTION) STYLE = MB_ICONQUESTION;
93// if (Style == WARNING) STYLE = MB_ICONWARNING;
94//
95// return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
96//#else
97 printf("%s\n", text);
98 return true;
99//#endif
100}
101
102// Default (non) translator
103std::string DefaultStringTranslator(const char* text)
104{
105 return text;
106}
107
diff --git a/src/common/src/msg_handler.h b/src/common/src/msg_handler.h
new file mode 100644
index 000000000..7de10c7b0
--- /dev/null
+++ b/src/common/src/msg_handler.h
@@ -0,0 +1,73 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _MSGHANDLER_H_
6#define _MSGHANDLER_H_
7
8#include <string>
9
10// Message alerts
11enum MSG_TYPE
12{
13 INFORMATION,
14 QUESTION,
15 WARNING,
16 CRITICAL
17};
18
19typedef bool (*MsgAlertHandler)(const char* caption, const char* text,
20 bool yes_no, int Style);
21typedef std::string (*StringTranslator)(const char* text);
22
23void RegisterMsgAlertHandler(MsgAlertHandler handler);
24void RegisterStringTranslator(StringTranslator translator);
25
26extern bool MsgAlert(bool yes_no, int Style, const char* format, ...)
27#ifdef __GNUC__
28 __attribute__((format(printf, 3, 4)))
29#endif
30 ;
31void SetEnableAlert(bool enable);
32
33#ifndef GEKKO
34#ifdef _WIN32
35 #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
36 #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
37 #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
38 #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
39 #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
40 // Use these macros (that do the same thing) if the message should be translated.
41 #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
42 #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
43 #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
44 #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
45 #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
46#else
47 #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
48 #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
49 #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
50 #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
51 #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
52 // Use these macros (that do the same thing) if the message should be translated.
53 #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
54 #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
55 #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
56 #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
57 #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
58#endif
59#else
60// GEKKO
61 #define SuccessAlert(format, ...) ;
62 #define PanicAlert(format, ...) ;
63 #define PanicYesNo(format, ...) ;
64 #define AskYesNo(format, ...) ;
65 #define CriticalAlert(format, ...) ;
66 #define SuccessAlertT(format, ...) ;
67 #define PanicAlertT(format, ...) ;
68 #define PanicYesNoT(format, ...) ;
69 #define AskYesNoT(format, ...) ;
70 #define CriticalAlertT(format, ...) ;
71#endif
72
73#endif // _MSGHANDLER_H_
diff --git a/src/common/src/scm_rev.h b/src/common/src/scm_rev.h
new file mode 100644
index 000000000..cb4eccfd0
--- /dev/null
+++ b/src/common/src/scm_rev.h
@@ -0,0 +1,4 @@
1#define SCM_REV_STR "7d11f8cedd7c135d96880f19ecbd3ff87a60a11f"
2#define SCM_DESC_STR "3.5-254-dirty"
3#define SCM_BRANCH_STR "master"
4#define SCM_IS_MASTER 1
diff --git a/src/common/src/std_condition_variable.h b/src/common/src/std_condition_variable.h
new file mode 100644
index 000000000..d44545e61
--- /dev/null
+++ b/src/common/src/std_condition_variable.h
@@ -0,0 +1,170 @@
1
2#ifndef CONDITION_VARIABLE_H_
3#define CONDITION_VARIABLE_H_
4
5#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
6#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
7
8#ifndef __has_include
9#define __has_include(s) 0
10#endif
11
12#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
13
14// GCC 4.4 provides <condition_variable>
15#include <condition_variable>
16
17#elif __has_include(<condition_variable>) && !ANDROID
18
19// clang and libc++ provide <condition_variable> on OSX. However, the version
20// of libc++ bundled with OSX 10.7 and 10.8 is buggy: it uses _ as a variable.
21//
22// We work around this issue by undefining and redefining _.
23
24#undef _
25#include <condition_variable>
26#define _(s) wxGetTranslation((s))
27
28#else
29
30// partial std::condition_variable implementation for win32/pthread
31
32#include "std_mutex.h"
33
34#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
35#define USE_RVALUE_REFERENCES
36#endif
37
38#if defined(_WIN32) && defined(_M_X64)
39#define USE_CONDITION_VARIABLES
40#elif defined(_WIN32)
41#define USE_EVENTS
42#endif
43
44namespace std
45{
46
47class condition_variable
48{
49#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
50 typedef CONDITION_VARIABLE native_type;
51#elif defined(_WIN32)
52 typedef HANDLE native_type;
53#else
54 typedef pthread_cond_t native_type;
55#endif
56
57public:
58
59#ifdef USE_EVENTS
60 typedef native_type native_handle_type;
61#else
62 typedef native_type* native_handle_type;
63#endif
64
65 condition_variable()
66 {
67#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
68 InitializeConditionVariable(&m_handle);
69#elif defined(_WIN32)
70 m_handle = CreateEvent(NULL, false, false, NULL);
71#else
72 pthread_cond_init(&m_handle, NULL);
73#endif
74 }
75
76 ~condition_variable()
77 {
78#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
79 CloseHandle(m_handle);
80#elif !defined(_WIN32)
81 pthread_cond_destroy(&m_handle);
82#endif
83 }
84
85 condition_variable(const condition_variable&) /*= delete*/;
86 condition_variable& operator=(const condition_variable&) /*= delete*/;
87
88 void notify_one()
89 {
90#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
91 WakeConditionVariable(&m_handle);
92#elif defined(_WIN32)
93 SetEvent(m_handle);
94#else
95 pthread_cond_signal(&m_handle);
96#endif
97 }
98
99 void notify_all()
100 {
101#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
102 WakeAllConditionVariable(&m_handle);
103#elif defined(_WIN32)
104 // TODO: broken
105 SetEvent(m_handle);
106#else
107 pthread_cond_broadcast(&m_handle);
108#endif
109 }
110
111 void wait(unique_lock<mutex>& lock)
112 {
113#ifdef _WIN32
114 #ifdef USE_SRWLOCKS
115 SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0);
116 #elif defined(USE_CONDITION_VARIABLES)
117 SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE);
118 #else
119 // TODO: broken, the unlock and wait need to be atomic
120 lock.unlock();
121 WaitForSingleObject(m_handle, INFINITE);
122 lock.lock();
123 #endif
124#else
125 pthread_cond_wait(&m_handle, lock.mutex()->native_handle());
126#endif
127 }
128
129 template <class Predicate>
130 void wait(unique_lock<mutex>& lock, Predicate pred)
131 {
132 while (!pred())
133 wait(lock);
134 }
135
136 //template <class Clock, class Duration>
137 //cv_status wait_until(unique_lock<mutex>& lock,
138 // const chrono::time_point<Clock, Duration>& abs_time);
139
140 //template <class Clock, class Duration, class Predicate>
141 // bool wait_until(unique_lock<mutex>& lock,
142 // const chrono::time_point<Clock, Duration>& abs_time,
143 // Predicate pred);
144
145 //template <class Rep, class Period>
146 //cv_status wait_for(unique_lock<mutex>& lock,
147 // const chrono::duration<Rep, Period>& rel_time);
148
149 //template <class Rep, class Period, class Predicate>
150 // bool wait_for(unique_lock<mutex>& lock,
151 // const chrono::duration<Rep, Period>& rel_time,
152 // Predicate pred);
153
154 native_handle_type native_handle()
155 {
156#ifdef USE_EVENTS
157 return m_handle;
158#else
159 return &m_handle;
160#endif
161 }
162
163private:
164 native_type m_handle;
165};
166
167}
168
169#endif
170#endif
diff --git a/src/common/src/std_mutex.h b/src/common/src/std_mutex.h
new file mode 100644
index 000000000..ce46a2f59
--- /dev/null
+++ b/src/common/src/std_mutex.h
@@ -0,0 +1,365 @@
1
2#ifndef MUTEX_H_
3#define MUTEX_H_
4
5#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
6#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
7
8#ifndef __has_include
9#define __has_include(s) 0
10#endif
11
12#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
13// GCC 4.4 provides <mutex>
14#include <mutex>
15#elif __has_include(<mutex>) && !ANDROID
16// Clang + libc++
17#include <mutex>
18#else
19
20// partial <mutex> implementation for win32/pthread
21
22#include <algorithm>
23
24#if defined(_WIN32)
25// WIN32
26#define WIN32_LEAN_AND_MEAN
27#include <Windows.h>
28
29#else
30// POSIX
31#include <pthread.h>
32
33#endif
34
35#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
36#define USE_RVALUE_REFERENCES
37#endif
38
39#if defined(_WIN32) && defined(_M_X64)
40#define USE_SRWLOCKS
41#endif
42
43namespace std
44{
45
46class recursive_mutex
47{
48#ifdef _WIN32
49 typedef CRITICAL_SECTION native_type;
50#else
51 typedef pthread_mutex_t native_type;
52#endif
53
54public:
55 typedef native_type* native_handle_type;
56
57 recursive_mutex(const recursive_mutex&) /*= delete*/;
58 recursive_mutex& operator=(const recursive_mutex&) /*= delete*/;
59
60 recursive_mutex()
61 {
62#ifdef _WIN32
63 InitializeCriticalSection(&m_handle);
64#else
65 pthread_mutexattr_t attr;
66 pthread_mutexattr_init(&attr);
67 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
68 pthread_mutex_init(&m_handle, &attr);
69#endif
70 }
71
72 ~recursive_mutex()
73 {
74#ifdef _WIN32
75 DeleteCriticalSection(&m_handle);
76#else
77 pthread_mutex_destroy(&m_handle);
78#endif
79 }
80
81 void lock()
82 {
83#ifdef _WIN32
84 EnterCriticalSection(&m_handle);
85#else
86 pthread_mutex_lock(&m_handle);
87#endif
88 }
89
90 void unlock()
91 {
92#ifdef _WIN32
93 LeaveCriticalSection(&m_handle);
94#else
95 pthread_mutex_unlock(&m_handle);
96#endif
97 }
98
99 bool try_lock()
100 {
101#ifdef _WIN32
102 return (0 != TryEnterCriticalSection(&m_handle));
103#else
104 return !pthread_mutex_trylock(&m_handle);
105#endif
106 }
107
108 native_handle_type native_handle()
109 {
110 return &m_handle;
111 }
112
113private:
114 native_type m_handle;
115};
116
117#if !defined(_WIN32) || defined(USE_SRWLOCKS)
118
119class mutex
120{
121#ifdef _WIN32
122 typedef SRWLOCK native_type;
123#else
124 typedef pthread_mutex_t native_type;
125#endif
126
127public:
128 typedef native_type* native_handle_type;
129
130 mutex(const mutex&) /*= delete*/;
131 mutex& operator=(const mutex&) /*= delete*/;
132
133 mutex()
134 {
135#ifdef _WIN32
136 InitializeSRWLock(&m_handle);
137#else
138 pthread_mutex_init(&m_handle, NULL);
139#endif
140 }
141
142 ~mutex()
143 {
144#ifdef _WIN32
145#else
146 pthread_mutex_destroy(&m_handle);
147#endif
148 }
149
150 void lock()
151 {
152#ifdef _WIN32
153 AcquireSRWLockExclusive(&m_handle);
154#else
155 pthread_mutex_lock(&m_handle);
156#endif
157 }
158
159 void unlock()
160 {
161#ifdef _WIN32
162 ReleaseSRWLockExclusive(&m_handle);
163#else
164 pthread_mutex_unlock(&m_handle);
165#endif
166 }
167
168 bool try_lock()
169 {
170#ifdef _WIN32
171 // XXX TryAcquireSRWLockExclusive requires Windows 7!
172 // return (0 != TryAcquireSRWLockExclusive(&m_handle));
173 return false;
174#else
175 return !pthread_mutex_trylock(&m_handle);
176#endif
177 }
178
179 native_handle_type native_handle()
180 {
181 return &m_handle;
182 }
183
184private:
185 native_type m_handle;
186};
187
188#else
189typedef recursive_mutex mutex; // just use CriticalSections
190
191#endif
192
193enum defer_lock_t { defer_lock };
194enum try_to_lock_t { try_to_lock };
195enum adopt_lock_t { adopt_lock };
196
197template <class Mutex>
198class lock_guard
199{
200public:
201 typedef Mutex mutex_type;
202
203 explicit lock_guard(mutex_type& m)
204 : pm(m)
205 {
206 m.lock();
207 }
208
209 lock_guard(mutex_type& m, adopt_lock_t)
210 : pm(m)
211 {
212 }
213
214 ~lock_guard()
215 {
216 pm.unlock();
217 }
218
219 lock_guard(lock_guard const&) /*= delete*/;
220 lock_guard& operator=(lock_guard const&) /*= delete*/;
221
222private:
223 mutex_type& pm;
224};
225
226template <class Mutex>
227class unique_lock
228{
229public:
230 typedef Mutex mutex_type;
231
232 unique_lock()
233 : pm(NULL), owns(false)
234 {}
235
236 /*explicit*/ unique_lock(mutex_type& m)
237 : pm(&m), owns(true)
238 {
239 m.lock();
240 }
241
242 unique_lock(mutex_type& m, defer_lock_t)
243 : pm(&m), owns(false)
244 {}
245
246 unique_lock(mutex_type& m, try_to_lock_t)
247 : pm(&m), owns(m.try_lock())
248 {}
249
250 unique_lock(mutex_type& m, adopt_lock_t)
251 : pm(&m), owns(true)
252 {}
253
254 //template <class Clock, class Duration>
255 //unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
256
257 //template <class Rep, class Period>
258 //unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
259
260 ~unique_lock()
261 {
262 if (owns_lock())
263 mutex()->unlock();
264 }
265
266#ifdef USE_RVALUE_REFERENCES
267 unique_lock& operator=(const unique_lock&) /*= delete*/;
268
269 unique_lock& operator=(unique_lock&& other)
270 {
271#else
272 unique_lock& operator=(const unique_lock& u)
273 {
274 // ugly const_cast to get around lack of rvalue references
275 unique_lock& other = const_cast<unique_lock&>(u);
276#endif
277 swap(other);
278 return *this;
279 }
280
281#ifdef USE_RVALUE_REFERENCES
282 unique_lock(const unique_lock&) /*= delete*/;
283
284 unique_lock(unique_lock&& other)
285 : pm(NULL), owns(false)
286 {
287#else
288 unique_lock(const unique_lock& u)
289 : pm(NULL), owns(false)
290 {
291 // ugly const_cast to get around lack of rvalue references
292 unique_lock& other = const_cast<unique_lock&>(u);
293#endif
294 swap(other);
295 }
296
297 void lock()
298 {
299 mutex()->lock();
300 owns = true;
301 }
302
303 bool try_lock()
304 {
305 owns = mutex()->try_lock();
306 return owns;
307 }
308
309 //template <class Rep, class Period>
310 //bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
311 //template <class Clock, class Duration>
312 //bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
313
314 void unlock()
315 {
316 mutex()->unlock();
317 owns = false;
318 }
319
320 void swap(unique_lock& u)
321 {
322 std::swap(pm, u.pm);
323 std::swap(owns, u.owns);
324 }
325
326 mutex_type* release()
327 {
328 auto const ret = mutex();
329
330 pm = NULL;
331 owns = false;
332
333 return ret;
334 }
335
336 bool owns_lock() const
337 {
338 return owns;
339 }
340
341 //explicit operator bool () const
342 //{
343 // return owns_lock();
344 //}
345
346 mutex_type* mutex() const
347 {
348 return pm;
349 }
350
351private:
352 mutex_type* pm;
353 bool owns;
354};
355
356template <class Mutex>
357void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
358{
359 x.swap(y);
360}
361
362}
363
364#endif
365#endif
diff --git a/src/common/src/std_thread.h b/src/common/src/std_thread.h
new file mode 100644
index 000000000..e43d28344
--- /dev/null
+++ b/src/common/src/std_thread.h
@@ -0,0 +1,317 @@
1
2#ifndef STD_THREAD_H_
3#define STD_THREAD_H_
4
5#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
6#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
7
8#ifndef __has_include
9#define __has_include(s) 0
10#endif
11
12#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
13// GCC 4.4 provides <thread>
14#ifndef _GLIBCXX_USE_SCHED_YIELD
15#define _GLIBCXX_USE_SCHED_YIELD
16#endif
17#include <thread>
18#elif __has_include(<thread>) && !ANDROID
19// Clang + libc++
20#include <thread>
21#else
22
23// partial std::thread implementation for win32/pthread
24
25#include <algorithm>
26
27#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
28#define USE_RVALUE_REFERENCES
29#endif
30
31#ifdef __APPLE__
32#import <Foundation/NSAutoreleasePool.h>
33#endif
34
35#if defined(_WIN32)
36// WIN32
37
38#define WIN32_LEAN_AND_MEAN
39#include <Windows.h>
40
41#if defined(_MSC_VER) && defined(_MT)
42// When linking with LIBCMT (the multithreaded C library), Microsoft recommends
43// using _beginthreadex instead of CreateThread.
44#define USE_BEGINTHREADEX
45#include <process.h>
46#endif
47
48#ifdef USE_BEGINTHREADEX
49#define THREAD_ID unsigned
50#define THREAD_RETURN unsigned __stdcall
51#else
52#define THREAD_ID DWORD
53#define THREAD_RETURN DWORD WINAPI
54#endif
55#define THREAD_HANDLE HANDLE
56
57#else
58// PTHREAD
59
60#include <unistd.h>
61
62#ifndef _POSIX_THREADS
63#error unsupported platform (no pthreads?)
64#endif
65
66#include <pthread.h>
67
68#define THREAD_ID pthread_t
69#define THREAD_HANDLE pthread_t
70#define THREAD_RETURN void*
71
72#endif
73
74namespace std
75{
76
77class thread
78{
79public:
80 typedef THREAD_HANDLE native_handle_type;
81
82 class id
83 {
84 friend class thread;
85 public:
86 id() : m_thread(0) {}
87 id(THREAD_ID _id) : m_thread(_id) {}
88
89 bool operator==(const id& rhs) const
90 {
91 return m_thread == rhs.m_thread;
92 }
93
94 bool operator!=(const id& rhs) const
95 {
96 return !(*this == rhs);
97 }
98
99 bool operator<(const id& rhs) const
100 {
101 return m_thread < rhs.m_thread;
102 }
103
104 private:
105 THREAD_ID m_thread;
106 };
107
108 // no variadic template support in msvc
109 //template <typename C, typename... A>
110 //thread(C&& func, A&&... args);
111
112 template <typename C>
113 thread(C func)
114 {
115 StartThread(new Func<C>(func));
116 }
117
118 template <typename C, typename A>
119 thread(C func, A arg)
120 {
121 StartThread(new FuncArg<C, A>(func, arg));
122 }
123
124 thread() /*= default;*/ {}
125
126#ifdef USE_RVALUE_REFERENCES
127 thread(const thread&) /*= delete*/;
128
129 thread(thread&& other)
130 {
131#else
132 thread(const thread& t)
133 {
134 // ugly const_cast to get around lack of rvalue references
135 thread& other = const_cast<thread&>(t);
136#endif
137 swap(other);
138 }
139
140#ifdef USE_RVALUE_REFERENCES
141 thread& operator=(const thread&) /*= delete*/;
142
143 thread& operator=(thread&& other)
144 {
145#else
146 thread& operator=(const thread& t)
147 {
148 // ugly const_cast to get around lack of rvalue references
149 thread& other = const_cast<thread&>(t);
150#endif
151 if (joinable())
152 detach();
153 swap(other);
154 return *this;
155 }
156
157 ~thread()
158 {
159 if (joinable())
160 detach();
161 }
162
163 bool joinable() const
164 {
165 return m_id != id();
166 }
167
168 id get_id() const
169 {
170 return m_id;
171 }
172
173 native_handle_type native_handle()
174 {
175#ifdef _WIN32
176 return m_handle;
177#else
178 return m_id.m_thread;
179#endif
180 }
181
182 void join()
183 {
184#ifdef _WIN32
185 WaitForSingleObject(m_handle, INFINITE);
186 detach();
187#else
188 pthread_join(m_id.m_thread, NULL);
189 m_id = id();
190#endif
191 }
192
193 void detach()
194 {
195#ifdef _WIN32
196 CloseHandle(m_handle);
197#else
198 pthread_detach(m_id.m_thread);
199#endif
200 m_id = id();
201 }
202
203 void swap(thread& other)
204 {
205 std::swap(m_id, other.m_id);
206#ifdef _WIN32
207 std::swap(m_handle, other.m_handle);
208#endif
209 }
210
211 static unsigned hardware_concurrency()
212 {
213#ifdef _WIN32
214 SYSTEM_INFO sysinfo;
215 GetSystemInfo(&sysinfo);
216 return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
217#else
218 return 0;
219#endif
220 }
221
222private:
223 id m_id;
224
225#ifdef _WIN32
226 native_handle_type m_handle;
227#endif
228
229 template <typename F>
230 void StartThread(F* param)
231 {
232#ifdef USE_BEGINTHREADEX
233 m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
234#elif defined(_WIN32)
235 m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
236#else
237 pthread_attr_t attr;
238 pthread_attr_init(&attr);
239 pthread_attr_setstacksize(&attr, 1024 * 1024);
240 if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param))
241 m_id = id();
242#endif
243 }
244
245 template <typename C>
246 class Func
247 {
248 public:
249 Func(C _func) : func(_func) {}
250
251 void Run() { func(); }
252
253 private:
254 C const func;
255 };
256
257 template <typename C, typename A>
258 class FuncArg
259 {
260 public:
261 FuncArg(C _func, A _arg) : func(_func), arg(_arg) {}
262
263 void Run() { func(arg); }
264
265 private:
266 C const func;
267 A arg;
268 };
269
270 template <typename F>
271 static THREAD_RETURN RunAndDelete(void* param)
272 {
273#ifdef __APPLE__
274 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
275#endif
276 static_cast<F*>(param)->Run();
277 delete static_cast<F*>(param);
278#ifdef __APPLE__
279 [pool release];
280#endif
281 return 0;
282 }
283};
284
285namespace this_thread
286{
287
288inline void yield()
289{
290#ifdef _WIN32
291 SwitchToThread();
292#else
293 sleep(0);
294#endif
295}
296
297inline thread::id get_id()
298{
299#ifdef _WIN32
300 return GetCurrentThreadId();
301#else
302 return pthread_self();
303#endif
304}
305
306} // namespace this_thread
307
308} // namespace std
309
310#undef USE_RVALUE_REFERENCES
311#undef USE_BEGINTHREADEX
312#undef THREAD_ID
313#undef THREAD_RETURN
314#undef THREAD_HANDLE
315
316#endif
317#endif
diff --git a/src/common/src/string_util.cpp b/src/common/src/string_util.cpp
new file mode 100644
index 000000000..ff4c5dbe0
--- /dev/null
+++ b/src/common/src/string_util.cpp
@@ -0,0 +1,531 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <algorithm>
8
9#include "common.h"
10#include "common_paths.h"
11#include "string_util.h"
12
13#ifdef _WIN32
14 #include <Windows.h>
15#else
16 #include <iconv.h>
17 #include <errno.h>
18#endif
19
20// faster than sscanf
21bool AsciiToHex(const char* _szValue, u32& result)
22{
23 char *endptr = NULL;
24 const u32 value = strtoul(_szValue, &endptr, 16);
25
26 if (!endptr || *endptr)
27 return false;
28
29 result = value;
30 return true;
31}
32
33bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args)
34{
35 int writtenCount;
36
37#ifdef _WIN32
38 // You would think *printf are simple, right? Iterate on each character,
39 // if it's a format specifier handle it properly, etc.
40 //
41 // Nooooo. Not according to the C standard.
42 //
43 // According to the C99 standard (7.19.6.1 "The fprintf function")
44 // The format shall be a multibyte character sequence
45 //
46 // Because some character encodings might have '%' signs in the middle of
47 // a multibyte sequence (SJIS for example only specifies that the first
48 // byte of a 2 byte sequence is "high", the second byte can be anything),
49 // printf functions have to decode the multibyte sequences and try their
50 // best to not screw up.
51 //
52 // Unfortunately, on Windows, the locale for most languages is not UTF-8
53 // as we would need. Notably, for zh_TW, Windows chooses EUC-CN as the
54 // locale, and completely fails when trying to decode UTF-8 as EUC-CN.
55 //
56 // On the other hand, the fix is simple: because we use UTF-8, no such
57 // multibyte handling is required as we can simply assume that no '%' char
58 // will be present in the middle of a multibyte sequence.
59 //
60 // This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l.
61 static locale_t c_locale = NULL;
62 if (!c_locale)
63 c_locale = _create_locale(LC_ALL, ".1252");
64 writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args);
65#else
66 writtenCount = vsnprintf(out, outsize, format, args);
67#endif
68
69 if (writtenCount > 0 && writtenCount < outsize)
70 {
71 out[writtenCount] = '\0';
72 return true;
73 }
74 else
75 {
76 out[outsize - 1] = '\0';
77 return false;
78 }
79}
80
81std::string StringFromFormat(const char* format, ...)
82{
83 va_list args;
84 char *buf = NULL;
85#ifdef _WIN32
86 int required = 0;
87
88 va_start(args, format);
89 required = _vscprintf(format, args);
90 buf = new char[required + 1];
91 CharArrayFromFormatV(buf, required + 1, format, args);
92 va_end(args);
93
94 std::string temp = buf;
95 delete[] buf;
96#else
97 va_start(args, format);
98 if (vasprintf(&buf, format, args) < 0)
99 ERROR_LOG(COMMON, "Unable to allocate memory for string");
100 va_end(args);
101
102 std::string temp = buf;
103 free(buf);
104#endif
105 return temp;
106}
107
108// For Debugging. Read out an u8 array.
109std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces)
110{
111 std::ostringstream oss;
112 oss << std::setfill('0') << std::hex;
113
114 for (int line = 0; size; ++data, --size)
115 {
116 oss << std::setw(2) << (int)*data;
117
118 if (line_len == ++line)
119 {
120 oss << '\n';
121 line = 0;
122 }
123 else if (spaces)
124 oss << ' ';
125 }
126
127 return oss.str();
128}
129
130// Turns " hej " into "hej". Also handles tabs.
131std::string StripSpaces(const std::string &str)
132{
133 const size_t s = str.find_first_not_of(" \t\r\n");
134
135 if (str.npos != s)
136 return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1);
137 else
138 return "";
139}
140
141// "\"hello\"" is turned to "hello"
142// This one assumes that the string has already been space stripped in both
143// ends, as done by StripSpaces above, for example.
144std::string StripQuotes(const std::string& s)
145{
146 if (s.size() && '\"' == s[0] && '\"' == *s.rbegin())
147 return s.substr(1, s.size() - 2);
148 else
149 return s;
150}
151
152bool TryParse(const std::string &str, u32 *const output)
153{
154 char *endptr = NULL;
155
156 // Reset errno to a value other than ERANGE
157 errno = 0;
158
159 unsigned long value = strtoul(str.c_str(), &endptr, 0);
160
161 if (!endptr || *endptr)
162 return false;
163
164 if (errno == ERANGE)
165 return false;
166
167#if ULONG_MAX > UINT_MAX
168 if (value >= 0x100000000ull
169 && value <= 0xFFFFFFFF00000000ull)
170 return false;
171#endif
172
173 *output = static_cast<u32>(value);
174 return true;
175}
176
177bool TryParse(const std::string &str, bool *const output)
178{
179 if ("1" == str || !strcasecmp("true", str.c_str()))
180 *output = true;
181 else if ("0" == str || !strcasecmp("false", str.c_str()))
182 *output = false;
183 else
184 return false;
185
186 return true;
187}
188
189std::string StringFromInt(int value)
190{
191 char temp[16];
192 sprintf(temp, "%i", value);
193 return temp;
194}
195
196std::string StringFromBool(bool value)
197{
198 return value ? "True" : "False";
199}
200
201bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
202{
203 if (full_path.empty())
204 return false;
205
206 size_t dir_end = full_path.find_last_of("/"
207 // windows needs the : included for something like just "C:" to be considered a directory
208#ifdef _WIN32
209 ":"
210#endif
211 );
212 if (std::string::npos == dir_end)
213 dir_end = 0;
214 else
215 dir_end += 1;
216
217 size_t fname_end = full_path.rfind('.');
218 if (fname_end < dir_end || std::string::npos == fname_end)
219 fname_end = full_path.size();
220
221 if (_pPath)
222 *_pPath = full_path.substr(0, dir_end);
223
224 if (_pFilename)
225 *_pFilename = full_path.substr(dir_end, fname_end - dir_end);
226
227 if (_pExtension)
228 *_pExtension = full_path.substr(fname_end);
229
230 return true;
231}
232
233void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename)
234{
235 _CompleteFilename = _Path;
236
237 // check for seperator
238 if (DIR_SEP_CHR != *_CompleteFilename.rbegin())
239 _CompleteFilename += DIR_SEP_CHR;
240
241 // add the filename
242 _CompleteFilename += _Filename;
243}
244
245void SplitString(const std::string& str, const char delim, std::vector<std::string>& output)
246{
247 std::istringstream iss(str);
248 output.resize(1);
249
250 while (std::getline(iss, *output.rbegin(), delim))
251 output.push_back("");
252
253 output.pop_back();
254}
255
256std::string TabsToSpaces(int tab_size, const std::string &in)
257{
258 const std::string spaces(tab_size, ' ');
259 std::string out(in);
260
261 size_t i = 0;
262 while (out.npos != (i = out.find('\t')))
263 out.replace(i, 1, spaces);
264
265 return out;
266}
267
268std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest)
269{
270 while(1)
271 {
272 size_t pos = result.find(src);
273 if (pos == std::string::npos) break;
274 result.replace(pos, src.size(), dest);
275 }
276 return result;
277}
278
279// UriDecode and UriEncode are from http://www.codeguru.com/cpp/cpp/string/conversions/print.php/c12759
280// by jinq0123 (November 2, 2006)
281
282// Uri encode and decode.
283// RFC1630, RFC1738, RFC2396
284
285//#include <string>
286//#include <assert.h>
287
288const char HEX2DEC[256] =
289{
290 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
291 /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
292 /* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
293 /* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
294 /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16,
295
296 /* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
297 /* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
298 /* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
299 /* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
300
301 /* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
302 /* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
303 /* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
304 /* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
305
306 /* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
307 /* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
308 /* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
309 /* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16
310};
311
312std::string UriDecode(const std::string & sSrc)
313{
314 // Note from RFC1630: "Sequences which start with a percent sign
315 // but are not followed by two hexadecimal characters (0-9, A-F) are reserved
316 // for future extension"
317
318 const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
319 const size_t SRC_LEN = sSrc.length();
320 const unsigned char * const SRC_END = pSrc + SRC_LEN;
321 const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%'
322
323 char * const pStart = new char[SRC_LEN];
324 char * pEnd = pStart;
325
326 while (pSrc < SRC_LAST_DEC)
327 {
328 if (*pSrc == '%')
329 {
330 char dec1, dec2;
331 if (16 != (dec1 = HEX2DEC[*(pSrc + 1)])
332 && 16 != (dec2 = HEX2DEC[*(pSrc + 2)]))
333 {
334 *pEnd++ = (dec1 << 4) + dec2;
335 pSrc += 3;
336 continue;
337 }
338 }
339
340 *pEnd++ = *pSrc++;
341 }
342
343 // the last 2- chars
344 while (pSrc < SRC_END)
345 *pEnd++ = *pSrc++;
346
347 std::string sResult(pStart, pEnd);
348 delete [] pStart;
349 return sResult;
350}
351
352// Only alphanum is safe.
353const char SAFE[256] =
354{
355 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
356 /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
357 /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
358 /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
359 /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0,
360
361 /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
362 /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
363 /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
364 /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
365
366 /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
367 /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
368 /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
369 /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
370
371 /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
372 /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
373 /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
374 /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
375};
376
377std::string UriEncode(const std::string & sSrc)
378{
379 const char DEC2HEX[16 + 1] = "0123456789ABCDEF";
380 const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
381 const size_t SRC_LEN = sSrc.length();
382 unsigned char * const pStart = new unsigned char[SRC_LEN * 3];
383 unsigned char * pEnd = pStart;
384 const unsigned char * const SRC_END = pSrc + SRC_LEN;
385
386 for (; pSrc < SRC_END; ++pSrc)
387 {
388 if (SAFE[*pSrc])
389 *pEnd++ = *pSrc;
390 else
391 {
392 // escape this char
393 *pEnd++ = '%';
394 *pEnd++ = DEC2HEX[*pSrc >> 4];
395 *pEnd++ = DEC2HEX[*pSrc & 0x0F];
396 }
397 }
398
399 std::string sResult((char *)pStart, (char *)pEnd);
400 delete [] pStart;
401 return sResult;
402}
403
404#ifdef _WIN32
405
406std::string UTF16ToUTF8(const std::wstring& input)
407{
408 auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr);
409
410 std::string output;
411 output.resize(size);
412
413 if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr))
414 output.clear();
415
416 return output;
417}
418
419std::wstring CPToUTF16(u32 code_page, const std::string& input)
420{
421 auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0);
422
423 std::wstring output;
424 output.resize(size);
425
426 if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size()))
427 output.clear();
428
429 return output;
430}
431
432std::wstring UTF8ToUTF16(const std::string& input)
433{
434 return CPToUTF16(CP_UTF8, input);
435}
436
437std::string SHIFTJISToUTF8(const std::string& input)
438{
439 return UTF16ToUTF8(CPToUTF16(932, input));
440}
441
442std::string CP1252ToUTF8(const std::string& input)
443{
444 return UTF16ToUTF8(CPToUTF16(1252, input));
445}
446
447#else
448
449template <typename T>
450std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
451{
452 std::string result;
453
454 iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
455 if ((iconv_t)-1 == conv_desc)
456 {
457 ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
458 }
459 else
460 {
461 size_t const in_bytes = sizeof(T) * input.size();
462 size_t const out_buffer_size = 4 * in_bytes;
463
464 std::string out_buffer;
465 out_buffer.resize(out_buffer_size);
466
467 auto src_buffer = &input[0];
468 size_t src_bytes = in_bytes;
469 auto dst_buffer = &out_buffer[0];
470 size_t dst_bytes = out_buffer.size();
471
472 while (src_bytes != 0)
473 {
474 size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
475 &dst_buffer, &dst_bytes);
476
477 if ((size_t)-1 == iconv_result)
478 {
479 if (EILSEQ == errno || EINVAL == errno)
480 {
481 // Try to skip the bad character
482 if (src_bytes != 0)
483 {
484 --src_bytes;
485 ++src_buffer;
486 }
487 }
488 else
489 {
490 ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
491 break;
492 }
493 }
494 }
495
496 out_buffer.resize(out_buffer_size - dst_bytes);
497 out_buffer.swap(result);
498
499 iconv_close(conv_desc);
500 }
501
502 return result;
503}
504
505std::string CP1252ToUTF8(const std::string& input)
506{
507 //return CodeToUTF8("CP1252//TRANSLIT", input);
508 //return CodeToUTF8("CP1252//IGNORE", input);
509 return CodeToUTF8("CP1252", input);
510}
511
512std::string SHIFTJISToUTF8(const std::string& input)
513{
514 //return CodeToUTF8("CP932", input);
515 return CodeToUTF8("SJIS", input);
516}
517
518std::string UTF16ToUTF8(const std::wstring& input)
519{
520 std::string result =
521 // CodeToUTF8("UCS-2", input);
522 // CodeToUTF8("UCS-2LE", input);
523 // CodeToUTF8("UTF-16", input);
524 CodeToUTF8("UTF-16LE", input);
525
526 // TODO: why is this needed?
527 result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
528 return result;
529}
530
531#endif
diff --git a/src/common/src/string_util.h b/src/common/src/string_util.h
new file mode 100644
index 000000000..31eaeb246
--- /dev/null
+++ b/src/common/src/string_util.h
@@ -0,0 +1,111 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _STRINGUTIL_H_
6#define _STRINGUTIL_H_
7
8#include <stdarg.h>
9
10#include <vector>
11#include <string>
12#include <sstream>
13#include <iomanip>
14
15#include "common.h"
16
17std::string StringFromFormat(const char* format, ...);
18// Cheap!
19bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args);
20
21template<size_t Count>
22inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...)
23{
24 va_list args;
25 va_start(args, format);
26 CharArrayFromFormatV(out, Count, format, args);
27 va_end(args);
28}
29
30// Good
31std::string ArrayToString(const u8 *data, u32 size, int line_len = 20, bool spaces = true);
32
33std::string StripSpaces(const std::string &s);
34std::string StripQuotes(const std::string &s);
35
36// Thousand separator. Turns 12345678 into 12,345,678
37template <typename I>
38std::string ThousandSeparate(I value, int spaces = 0)
39{
40 std::ostringstream oss;
41
42// std::locale("") seems to be broken on many platforms
43#if defined _WIN32 || (defined __linux__ && !defined __clang__)
44 oss.imbue(std::locale(""));
45#endif
46 oss << std::setw(spaces) << value;
47
48 return oss.str();
49}
50
51std::string StringFromInt(int value);
52std::string StringFromBool(bool value);
53
54bool TryParse(const std::string &str, bool *output);
55bool TryParse(const std::string &str, u32 *output);
56
57template <typename N>
58static bool TryParse(const std::string &str, N *const output)
59{
60 std::istringstream iss(str);
61
62 N tmp = 0;
63 if (iss >> tmp)
64 {
65 *output = tmp;
66 return true;
67 }
68 else
69 return false;
70}
71
72// TODO: kill this
73bool AsciiToHex(const char* _szValue, u32& result);
74
75std::string TabsToSpaces(int tab_size, const std::string &in);
76
77void SplitString(const std::string& str, char delim, std::vector<std::string>& output);
78
79// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe"
80bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension);
81
82void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename);
83std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest);
84std::string UriDecode(const std::string & sSrc);
85std::string UriEncode(const std::string & sSrc);
86
87std::string CP1252ToUTF8(const std::string& str);
88std::string SHIFTJISToUTF8(const std::string& str);
89std::string UTF16ToUTF8(const std::wstring& str);
90
91#ifdef _WIN32
92
93std::wstring UTF8ToUTF16(const std::string& str);
94
95#ifdef _UNICODE
96inline std::string TStrToUTF8(const std::wstring& str)
97{ return UTF16ToUTF8(str); }
98
99inline std::wstring UTF8ToTStr(const std::string& str)
100{ return UTF8ToUTF16(str); }
101#else
102inline std::string TStrToUTF8(const std::string& str)
103{ return str; }
104
105inline std::string UTF8ToTStr(const std::string& str)
106{ return str; }
107#endif
108
109#endif
110
111#endif // _STRINGUTIL_H_
diff --git a/src/common/src/thread.cpp b/src/common/src/thread.cpp
new file mode 100644
index 000000000..e75dfffeb
--- /dev/null
+++ b/src/common/src/thread.cpp
@@ -0,0 +1,133 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "thread.h"
6#include "common.h"
7
8#ifdef __APPLE__
9#include <mach/mach.h>
10#elif defined BSD4_4
11#include <pthread_np.h>
12#endif
13
14#ifdef USE_BEGINTHREADEX
15#include <process.h>
16#endif
17
18namespace Common
19{
20
21int CurrentThreadId()
22{
23#ifdef _WIN32
24 return GetCurrentThreadId();
25#elif defined __APPLE__
26 return mach_thread_self();
27#else
28 return 0;
29#endif
30}
31
32#ifdef _WIN32
33
34void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
35{
36 SetThreadAffinityMask(thread, mask);
37}
38
39void SetCurrentThreadAffinity(u32 mask)
40{
41 SetThreadAffinityMask(GetCurrentThread(), mask);
42}
43
44// Supporting functions
45void SleepCurrentThread(int ms)
46{
47 Sleep(ms);
48}
49
50void SwitchCurrentThread()
51{
52 SwitchToThread();
53}
54
55// Sets the debugger-visible name of the current thread.
56// Uses undocumented (actually, it is now documented) trick.
57// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
58
59// This is implemented much nicer in upcoming msvc++, see:
60// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
61void SetCurrentThreadName(const char* szThreadName)
62{
63 static const DWORD MS_VC_EXCEPTION = 0x406D1388;
64
65 #pragma pack(push,8)
66 struct THREADNAME_INFO
67 {
68 DWORD dwType; // must be 0x1000
69 LPCSTR szName; // pointer to name (in user addr space)
70 DWORD dwThreadID; // thread ID (-1=caller thread)
71 DWORD dwFlags; // reserved for future use, must be zero
72 } info;
73 #pragma pack(pop)
74
75 info.dwType = 0x1000;
76 info.szName = szThreadName;
77 info.dwThreadID = -1; //dwThreadID;
78 info.dwFlags = 0;
79
80 __try
81 {
82 RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
83 }
84 __except(EXCEPTION_CONTINUE_EXECUTION)
85 {}
86}
87
88#else // !WIN32, so must be POSIX threads
89
90void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
91{
92#ifdef __APPLE__
93 thread_policy_set(pthread_mach_thread_np(thread),
94 THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1);
95#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID)
96 cpu_set_t cpu_set;
97 CPU_ZERO(&cpu_set);
98
99 for (int i = 0; i != sizeof(mask) * 8; ++i)
100 if ((mask >> i) & 1)
101 CPU_SET(i, &cpu_set);
102
103 pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set);
104#endif
105}
106
107void SetCurrentThreadAffinity(u32 mask)
108{
109 SetThreadAffinity(pthread_self(), mask);
110}
111
112void SleepCurrentThread(int ms)
113{
114 usleep(1000 * ms);
115}
116
117void SwitchCurrentThread()
118{
119 usleep(1000 * 1);
120}
121
122void SetCurrentThreadName(const char* szThreadName)
123{
124#ifdef __APPLE__
125 pthread_setname_np(szThreadName);
126#else
127 pthread_setname_np(pthread_self(), szThreadName);
128#endif
129}
130
131#endif
132
133} // namespace Common
diff --git a/src/common/src/thread.h b/src/common/src/thread.h
new file mode 100644
index 000000000..3178c40f7
--- /dev/null
+++ b/src/common/src/thread.h
@@ -0,0 +1,156 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _THREAD_H_
6#define _THREAD_H_
7
8#include "std_condition_variable.h"
9#include "std_mutex.h"
10#include "std_thread.h"
11
12// Don't include common.h here as it will break LogManager
13#include "common_types.h"
14#include <stdio.h>
15#include <string.h>
16
17// This may not be defined outside _WIN32
18#ifndef _WIN32
19#ifndef INFINITE
20#define INFINITE 0xffffffff
21#endif
22
23//for gettimeofday and struct time(spec|val)
24#include <time.h>
25#include <sys/time.h>
26#endif
27
28namespace Common
29{
30
31int CurrentThreadId();
32
33void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
34void SetCurrentThreadAffinity(u32 mask);
35
36class Event
37{
38public:
39 Event()
40 : is_set(false)
41 {};
42
43 void Set()
44 {
45 std::lock_guard<std::mutex> lk(m_mutex);
46 if (!is_set)
47 {
48 is_set = true;
49 m_condvar.notify_one();
50 }
51 }
52
53 void Wait()
54 {
55 std::unique_lock<std::mutex> lk(m_mutex);
56 m_condvar.wait(lk, IsSet(this));
57 is_set = false;
58 }
59
60 void Reset()
61 {
62 std::unique_lock<std::mutex> lk(m_mutex);
63 // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
64 is_set = false;
65 }
66
67private:
68 class IsSet
69 {
70 public:
71 IsSet(const Event* ev)
72 : m_event(ev)
73 {}
74
75 bool operator()()
76 {
77 return m_event->is_set;
78 }
79
80 private:
81 const Event* const m_event;
82 };
83
84 volatile bool is_set;
85 std::condition_variable m_condvar;
86 std::mutex m_mutex;
87};
88
89// TODO: doesn't work on windows with (count > 2)
90class Barrier
91{
92public:
93 Barrier(size_t count)
94 : m_count(count), m_waiting(0)
95 {}
96
97 // block until "count" threads call Sync()
98 bool Sync()
99 {
100 std::unique_lock<std::mutex> lk(m_mutex);
101
102 // TODO: broken when next round of Sync()s
103 // is entered before all waiting threads return from the notify_all
104
105 if (m_count == ++m_waiting)
106 {
107 m_waiting = 0;
108 m_condvar.notify_all();
109 return true;
110 }
111 else
112 {
113 m_condvar.wait(lk, IsDoneWating(this));
114 return false;
115 }
116 }
117
118private:
119 class IsDoneWating
120 {
121 public:
122 IsDoneWating(const Barrier* bar)
123 : m_bar(bar)
124 {}
125
126 bool operator()()
127 {
128 return (0 == m_bar->m_waiting);
129 }
130
131 private:
132 const Barrier* const m_bar;
133 };
134
135 std::condition_variable m_condvar;
136 std::mutex m_mutex;
137 const size_t m_count;
138 volatile size_t m_waiting;
139};
140
141void SleepCurrentThread(int ms);
142void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
143
144// Use this function during a spin-wait to make the current thread
145// relax while another thread is working. This may be more efficient
146// than using events because event functions use kernel calls.
147inline void YieldCPU()
148{
149 std::this_thread::yield();
150}
151
152void SetCurrentThreadName(const char *name);
153
154} // namespace Common
155
156#endif // _THREAD_H_
diff --git a/src/common/src/thunk.h b/src/common/src/thunk.h
new file mode 100644
index 000000000..4b64a9b0e
--- /dev/null
+++ b/src/common/src/thunk.h
@@ -0,0 +1,46 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _THUNK_H_
6#define _THUNK_H_
7
8#include <map>
9
10#include "common.h"
11#include "x64Emitter.h"
12
13// This simple class creates a wrapper around a C/C++ function that saves all fp state
14// before entering it, and restores it upon exit. This is required to be able to selectively
15// call functions from generated code, without inflicting the performance hit and increase
16// of complexity that it means to protect the generated code from this problem.
17
18// This process is called thunking.
19
20// There will only ever be one level of thunking on the stack, plus,
21// we don't want to pollute the stack, so we store away regs somewhere global.
22// NOT THREAD SAFE. This may only be used from the CPU thread.
23// Any other thread using this stuff will be FATAL.
24
25class ThunkManager : public Gen::XCodeBlock
26{
27 std::map<void *, const u8 *> thunks;
28
29 const u8 *save_regs;
30 const u8 *load_regs;
31
32public:
33 ThunkManager() {
34 Init();
35 }
36 ~ThunkManager() {
37 Shutdown();
38 }
39 void *ProtectFunction(void *function, int num_params);
40private:
41 void Init();
42 void Shutdown();
43 void Reset();
44};
45
46#endif // _THUNK_H_
diff --git a/src/common/src/timer.cpp b/src/common/src/timer.cpp
new file mode 100644
index 000000000..0300133c5
--- /dev/null
+++ b/src/common/src/timer.cpp
@@ -0,0 +1,226 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <time.h>
6
7#ifdef _WIN32
8#include <Windows.h>
9#include <mmsystem.h>
10#include <sys/timeb.h>
11#else
12#include <sys/time.h>
13#endif
14
15#include "common.h"
16#include "timer.h"
17#include "string_util.h"
18
19namespace Common
20{
21
22u32 Timer::GetTimeMs()
23{
24#ifdef _WIN32
25 return timeGetTime();
26#else
27 struct timeval t;
28 (void)gettimeofday(&t, NULL);
29 return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000));
30#endif
31}
32
33// --------------------------------------------
34// Initiate, Start, Stop, and Update the time
35// --------------------------------------------
36
37// Set initial values for the class
38Timer::Timer()
39 : m_LastTime(0), m_StartTime(0), m_Running(false)
40{
41 Update();
42}
43
44// Write the starting time
45void Timer::Start()
46{
47 m_StartTime = GetTimeMs();
48 m_Running = true;
49}
50
51// Stop the timer
52void Timer::Stop()
53{
54 // Write the final time
55 m_LastTime = GetTimeMs();
56 m_Running = false;
57}
58
59// Update the last time variable
60void Timer::Update()
61{
62 m_LastTime = GetTimeMs();
63 //TODO(ector) - QPF
64}
65
66// -------------------------------------
67// Get time difference and elapsed time
68// -------------------------------------
69
70// Get the number of milliseconds since the last Update()
71u64 Timer::GetTimeDifference()
72{
73 return GetTimeMs() - m_LastTime;
74}
75
76// Add the time difference since the last Update() to the starting time.
77// This is used to compensate for a paused game.
78void Timer::AddTimeDifference()
79{
80 m_StartTime += GetTimeDifference();
81}
82
83// Get the time elapsed since the Start()
84u64 Timer::GetTimeElapsed()
85{
86 // If we have not started yet, return 1 (because then I don't
87 // have to change the FPS calculation in CoreRerecording.cpp .
88 if (m_StartTime == 0) return 1;
89
90 // Return the final timer time if the timer is stopped
91 if (!m_Running) return (m_LastTime - m_StartTime);
92
93 return (GetTimeMs() - m_StartTime);
94}
95
96// Get the formatted time elapsed since the Start()
97std::string Timer::GetTimeElapsedFormatted() const
98{
99 // If we have not started yet, return zero
100 if (m_StartTime == 0)
101 return "00:00:00:000";
102
103 // The number of milliseconds since the start.
104 // Use a different value if the timer is stopped.
105 u64 Milliseconds;
106 if (m_Running)
107 Milliseconds = GetTimeMs() - m_StartTime;
108 else
109 Milliseconds = m_LastTime - m_StartTime;
110 // Seconds
111 u32 Seconds = (u32)(Milliseconds / 1000);
112 // Minutes
113 u32 Minutes = Seconds / 60;
114 // Hours
115 u32 Hours = Minutes / 60;
116
117 std::string TmpStr = StringFromFormat("%02i:%02i:%02i:%03i",
118 Hours, Minutes % 60, Seconds % 60, Milliseconds % 1000);
119 return TmpStr;
120}
121
122// Get current time
123void Timer::IncreaseResolution()
124{
125#ifdef _WIN32
126 timeBeginPeriod(1);
127#endif
128}
129
130void Timer::RestoreResolution()
131{
132#ifdef _WIN32
133 timeEndPeriod(1);
134#endif
135}
136
137// Get the number of seconds since January 1 1970
138u64 Timer::GetTimeSinceJan1970()
139{
140 time_t ltime;
141 time(&ltime);
142 return((u64)ltime);
143}
144
145u64 Timer::GetLocalTimeSinceJan1970()
146{
147 time_t sysTime, tzDiff, tzDST;
148 struct tm * gmTime;
149
150 time(&sysTime);
151
152 // Account for DST where needed
153 gmTime = localtime(&sysTime);
154 if(gmTime->tm_isdst == 1)
155 tzDST = 3600;
156 else
157 tzDST = 0;
158
159 // Lazy way to get local time in sec
160 gmTime = gmtime(&sysTime);
161 tzDiff = sysTime - mktime(gmTime);
162
163 return (u64)(sysTime + tzDiff + tzDST);
164}
165
166// Return the current time formatted as Minutes:Seconds:Milliseconds
167// in the form 00:00:000.
168std::string Timer::GetTimeFormatted()
169{
170 time_t sysTime;
171 struct tm * gmTime;
172 char formattedTime[13];
173 char tmp[13];
174
175 time(&sysTime);
176 gmTime = localtime(&sysTime);
177
178 strftime(tmp, 6, "%M:%S", gmTime);
179
180 // Now tack on the milliseconds
181#ifdef _WIN32
182 struct timeb tp;
183 (void)::ftime(&tp);
184 sprintf(formattedTime, "%s:%03i", tmp, tp.millitm);
185#else
186 struct timeval t;
187 (void)gettimeofday(&t, NULL);
188 sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000));
189#endif
190
191 return std::string(formattedTime);
192}
193
194// Returns a timestamp with decimals for precise time comparisons
195// ----------------
196double Timer::GetDoubleTime()
197{
198#ifdef _WIN32
199 struct timeb tp;
200 (void)::ftime(&tp);
201#else
202 struct timeval t;
203 (void)gettimeofday(&t, NULL);
204#endif
205 // Get continuous timestamp
206 u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970();
207
208 // Remove a few years. We only really want enough seconds to make
209 // sure that we are detecting actual actions, perhaps 60 seconds is
210 // enough really, but I leave a year of seconds anyway, in case the
211 // user's clock is incorrect or something like that.
212 TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
213
214 // Make a smaller integer that fits in the double
215 u32 Seconds = (u32)TmpSeconds;
216#ifdef _WIN32
217 double ms = tp.millitm / 1000.0 / 1000.0;
218#else
219 double ms = t.tv_usec / 1000000.0;
220#endif
221 double TmpTime = Seconds + ms;
222
223 return TmpTime;
224}
225
226} // Namespace Common
diff --git a/src/common/src/timer.h b/src/common/src/timer.h
new file mode 100644
index 000000000..9ee5719a3
--- /dev/null
+++ b/src/common/src/timer.h
@@ -0,0 +1,46 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _TIMER_H_
6#define _TIMER_H_
7
8#include "common.h"
9#include <string>
10
11namespace Common
12{
13class Timer
14{
15public:
16 Timer();
17
18 void Start();
19 void Stop();
20 void Update();
21
22 // The time difference is always returned in milliseconds, regardless of alternative internal representation
23 u64 GetTimeDifference();
24 void AddTimeDifference();
25
26 static void IncreaseResolution();
27 static void RestoreResolution();
28 static u64 GetTimeSinceJan1970();
29 static u64 GetLocalTimeSinceJan1970();
30 static double GetDoubleTime();
31
32 static std::string GetTimeFormatted();
33 std::string GetTimeElapsedFormatted() const;
34 u64 GetTimeElapsed();
35
36 static u32 GetTimeMs();
37
38private:
39 u64 m_LastTime;
40 u64 m_StartTime;
41 bool m_Running;
42};
43
44} // Namespace Common
45
46#endif // _TIMER_H_
diff --git a/src/common/src/version.cpp b/src/common/src/version.cpp
new file mode 100644
index 000000000..47d7b52ad
--- /dev/null
+++ b/src/common/src/version.cpp
@@ -0,0 +1,45 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common.h"
6#include "scm_rev.h"
7
8#ifdef _DEBUG
9 #define BUILD_TYPE_STR "Debug "
10#elif defined DEBUGFAST
11 #define BUILD_TYPE_STR "DebugFast "
12#else
13 #define BUILD_TYPE_STR ""
14#endif
15
16const char *scm_rev_str = "Dolphin "
17#if !SCM_IS_MASTER
18 "[" SCM_BRANCH_STR "] "
19#endif
20
21#ifdef __INTEL_COMPILER
22 BUILD_TYPE_STR SCM_DESC_STR "-ICC";
23#else
24 BUILD_TYPE_STR SCM_DESC_STR;
25#endif
26
27#ifdef _M_X64
28#define NP_ARCH "x64"
29#else
30#ifdef _M_ARM
31#define NP_ARCH "ARM"
32#else
33#define NP_ARCH "x86"
34#endif
35#endif
36
37#ifdef _WIN32
38const char *netplay_dolphin_ver = SCM_DESC_STR " W" NP_ARCH;
39#elif __APPLE__
40const char *netplay_dolphin_ver = SCM_DESC_STR " M" NP_ARCH;
41#else
42const char *netplay_dolphin_ver = SCM_DESC_STR " L" NP_ARCH;
43#endif
44
45const char *scm_rev_git_str = SCM_REV_STR;
diff --git a/vsprops/CodeGen_Debug.props b/vsprops/code_generation_debug.props
index b138f38e7..b138f38e7 100644
--- a/vsprops/CodeGen_Debug.props
+++ b/vsprops/code_generation_debug.props
diff --git a/vsprops/CodeGen_Release.props b/vsprops/code_generation_release.props
index 0a74151ce..0a74151ce 100644
--- a/vsprops/CodeGen_Release.props
+++ b/vsprops/code_generation_release.props