diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4e8b26e254..ecc8e6ea61 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,8 @@ option(ANDROID "Enables a build for Android" OFF)
option(USE_EGL "Enables EGL OpenGL Interface" OFF)
option(USE_X11 "Enables X11 Support" ON)
option(USE_WAYLAND "Enables Wayland Support" OFF)
-option(USE_GLES "Enables GLES And EGL, disables OGL" OFF)
+option(USE_GLES "Enables GLES2 And EGL, disables OGL" OFF)
+option(USE_GLES3 "Enables GLES3 and EGL" OFF)
option(DISABLE_WX "Disable wxWidgets (use CLI interface)" OFF)
option(FASTLOG "Enable all logs" OFF)
@@ -84,11 +85,11 @@ endfunction(enable_precompiled_headers)
include(FindGit OPTIONAL)
if(GIT_FOUND AND NOT DOLPHIN_WC_REVISION)
# defines DOLPHIN_WC_REVISION
- EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
+ EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
OUTPUT_VARIABLE DOLPHIN_WC_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE)
# defines DOLPHIN_WC_DESCRIBE
- EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} describe --always --long --dirty
+ EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --always --long --dirty
OUTPUT_VARIABLE DOLPHIN_WC_DESCRIBE
OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -96,7 +97,7 @@ if(GIT_FOUND AND NOT DOLPHIN_WC_REVISION)
STRING(REGEX REPLACE "-[^-]+((-dirty)?)$" "\\1" DOLPHIN_WC_DESCRIBE "${DOLPHIN_WC_DESCRIBE}")
# defines DOLPHIN_WC_BRANCH
- EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
+ EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
OUTPUT_VARIABLE DOLPHIN_WC_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
@@ -261,11 +262,19 @@ endif()
# For now GLES and EGL are tied to each other.
# Enabling GLES also disables the OpenGL plugin.
-if(USE_GLES)
- message("GLES rendering enabled")
- add_definitions(-DUSE_GLES=1)
- add_definitions(-DUSE_EGL=1)
+if(USE_GLES3)
+ message("GLES3 rendering enabled")
+ add_definitions(-DUSE_GLES=1 -DUSE_EGL=1 -DUSE_GLES3=1)
+ include_directories(Externals/GLES3)
set(USE_EGL True)
+ set(USE_GLES True)
+else()
+ if(USE_GLES)
+ message("GLES2 rendering enabled. OpenGL disabled")
+ add_definitions(-DUSE_GLES=1)
+ add_definitions(-DUSE_EGL=1)
+ set(USE_EGL True)
+ endif()
endif()
# For now Wayland and EGL are tied to each other.
# The alternative would be an shm path
@@ -595,7 +604,7 @@ if(NOT DISABLE_WX AND NOT ANDROID)
FIND_PACKAGE(wxWidgets COMPONENTS core aui adv)
if(wxWidgets_FOUND)
- EXECUTE_PROCESS(
+ EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}"
${wxWidgets_CONFIG_OPTIONS} --version
OUTPUT_VARIABLE wxWidgets_VERSION
@@ -610,7 +619,7 @@ if(NOT DISABLE_WX AND NOT ANDROID)
endif(wxWidgets_FOUND)
if(wxWidgets_FOUND)
- EXECUTE_PROCESS(
+ EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}"
${wxWidgets_CONFIG_OPTIONS} --version
OUTPUT_VARIABLE wxWidgets_VERSION
diff --git a/Data/User/GameConfig/GHMD4F.ini b/Data/User/GameConfig/GHMD4F.ini
new file mode 100644
index 0000000000..804c7ce141
--- /dev/null
+++ b/Data/User/GameConfig/GHMD4F.ini
@@ -0,0 +1,16 @@
+# GHMD4F - Hitman 2: Silent Assassin
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationIssues =
+EmulationStateId = 5
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GHME4F.ini b/Data/User/GameConfig/GHME4F.ini
index 9ad65bde82..dfce92de40 100644
--- a/Data/User/GameConfig/GHME4F.ini
+++ b/Data/User/GameConfig/GHME4F.ini
@@ -30,3 +30,11 @@ $Press Left + Y For Nailgun
52889D30 00000801
0406D250 418201BC
0406D288 408000C4
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GHMF4F.ini b/Data/User/GameConfig/GHMF4F.ini
new file mode 100644
index 0000000000..cf6dbb5494
--- /dev/null
+++ b/Data/User/GameConfig/GHMF4F.ini
@@ -0,0 +1,16 @@
+# GHMF4F - Hitman 2: Silent Assassin
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationIssues =
+EmulationStateId = 5
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GHMP4F.ini b/Data/User/GameConfig/GHMP4F.ini
new file mode 100644
index 0000000000..b9a7263c92
--- /dev/null
+++ b/Data/User/GameConfig/GHMP4F.ini
@@ -0,0 +1,16 @@
+# GHMP4F - Hitman 2: Silent Assassin
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationIssues =
+EmulationStateId = 5
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GJXP51.ini b/Data/User/GameConfig/GJXP51.ini
new file mode 100644
index 0000000000..e8d89a1d99
--- /dev/null
+++ b/Data/User/GameConfig/GJXP51.ini
@@ -0,0 +1,18 @@
+# GJXP51 - Vexx
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[EmuState]
+EmulationStateId = 4
+EmulationIssues = Slow because it needs mmu to run.
+[OnFrame]
+[ActionReplay]
+[Gecko]
+[Video_Settings]
+[Core]
+MMU = 1
+
diff --git a/Data/User/GameConfig/GOWD69.ini b/Data/User/GameConfig/GOWD69.ini
new file mode 100644
index 0000000000..b72311394e
--- /dev/null
+++ b/Data/User/GameConfig/GOWD69.ini
@@ -0,0 +1,16 @@
+# GOWD69 - NFS Most Wanted
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 4
+EmulationIssues = Videos are messed up, skip them.
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GOWE69.ini b/Data/User/GameConfig/GOWE69.ini
index 055236f92c..e3ec320abd 100644
--- a/Data/User/GameConfig/GOWE69.ini
+++ b/Data/User/GameConfig/GOWE69.ini
@@ -1,7 +1,16 @@
# GOWE69 - NFS Most Wanted
[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
EmulationStateId = 4
-EmulationIssues = Some GFX Glitches And may be slow.
+EmulationIssues = Videos are messed up, skip them.
[OnFrame] Add memory patches to be applied every frame here.
[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GOWF69.ini b/Data/User/GameConfig/GOWF69.ini
new file mode 100644
index 0000000000..a6e4e56de3
--- /dev/null
+++ b/Data/User/GameConfig/GOWF69.ini
@@ -0,0 +1,16 @@
+# GOWF69 - NFS Most Wanted
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 4
+EmulationIssues = Videos are messed up, skip them.
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GOWJ69.ini b/Data/User/GameConfig/GOWJ69.ini
new file mode 100644
index 0000000000..dfd9602e7e
--- /dev/null
+++ b/Data/User/GameConfig/GOWJ69.ini
@@ -0,0 +1,16 @@
+# GOWJ69 - NFS Most Wanted
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 4
+EmulationIssues = Videos are messed up, skip them.
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GOWP69.ini b/Data/User/GameConfig/GOWP69.ini
new file mode 100644
index 0000000000..9d85f68fb0
--- /dev/null
+++ b/Data/User/GameConfig/GOWP69.ini
@@ -0,0 +1,16 @@
+# GOWP69 - NFS Most Wanted
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 4
+EmulationIssues = Videos are messed up, skip them.
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Data/User/GameConfig/GWLX6L.ini b/Data/User/GameConfig/GWLX6L.ini
index ae259eb466..cd4408b3e5 100644
--- a/Data/User/GameConfig/GWLX6L.ini
+++ b/Data/User/GameConfig/GWLX6L.ini
@@ -1,8 +1,10 @@
# GWLX6L - Project Zoo
[Core] Values set here will override the main dolphin settings.
-TLBHack=1
+TLBHack = 1
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
-EmulationStateId = 2
-EmulationIssues = Unespecified codes,report to devs
+EmulationStateId = 4
+EmulationIssues =
[OnFrame] Add memory patches to be applied every frame here.
++$Bypass FIFO reset
+0x8028EE80:dword:0x48000638
[ActionReplay] Add action replay cheats here.
diff --git a/Data/User/GameConfig/GX2P52.ini b/Data/User/GameConfig/GX2P52.ini
new file mode 100644
index 0000000000..d57566d6f6
--- /dev/null
+++ b/Data/User/GameConfig/GX2P52.ini
@@ -0,0 +1,18 @@
+# GX2P52 - X-Men Legends 2: Rise of Apocalypse
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 3
+EmulationIssues =
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
+[Video_Enhancements]
+
diff --git a/Data/User/GameConfig/GX3P41.ini b/Data/User/GameConfig/GX3P41.ini
index f7d136347c..ed40ef469a 100644
--- a/Data/User/GameConfig/GX3P41.ini
+++ b/Data/User/GameConfig/GX3P41.ini
@@ -4,7 +4,7 @@ TLBHack = 1
MMU = 1
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
EmulationStateId = 4
-EmulationIssues = Needs real xfb for the videos to show up (r6906)
+EmulationIssues = Needs real xfb for the videos to show up.
[OnFrame] Add memory patches to be applied every frame here.
[ActionReplay] Add action replay cheats here.
[Video]
diff --git a/Data/User/GameConfig/GX3X41.ini b/Data/User/GameConfig/GX3X41.ini
new file mode 100644
index 0000000000..377ada9d50
--- /dev/null
+++ b/Data/User/GameConfig/GX3X41.ini
@@ -0,0 +1,21 @@
+# GX3X41 - XIII
+[Core] Values set here will override the main dolphin settings.
+TLBHack = 1
+MMU = 1
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 4
+EmulationIssues = Needs real xfb for the videos to show up.
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
+[Video_Settings]
+UseXFB = True
+UseRealXFB = True
+
diff --git a/Data/User/GameConfig/JAAE01.ini b/Data/User/GameConfig/JAAE01.ini
index ad577becc9..96dab75a98 100644
--- a/Data/User/GameConfig/JAAE01.ini
+++ b/Data/User/GameConfig/JAAE01.ini
@@ -1,8 +1,17 @@
-# JAAE01 - Super Mario World
-[Core] Values set here will override the main dolphin settings.
-[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
-EmulationIssues = No Sound
-EmulationStateId = 4
-[OnFrame] Add memory patches to be applied every frame here.
-[ActionReplay] Add action replay cheats here.
-[Video]
\ No newline at end of file
+# JAAE01 - Super Mario World
+[Core] Values set here will override the main dolphin settings.
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationIssues =
+EmulationStateId = 4
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
+[Video_Settings]
+SafeTextureCacheColorSamples = 512
diff --git a/Data/User/GameConfig/SB3E08.ini b/Data/User/GameConfig/SB3E08.ini
index 110fee08ed..ce8e25554e 100644
--- a/Data/User/GameConfig/SB3E08.ini
+++ b/Data/User/GameConfig/SB3E08.ini
@@ -1,7 +1,7 @@
# SB3E08 - BASARA
[Core] Values set here will override the main dolphin settings.
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
-EmulationIssues = Audio synch issues during dialogues, otherwise perfect
+EmulationIssues =
EmulationStateId = 5
[OnFrame] Add memory patches to be applied every frame here.
[ActionReplay] Add action replay cheats here.
diff --git a/Data/User/GameConfig/SB3J08.ini b/Data/User/GameConfig/SB3J08.ini
index e7b6b6a3ef..70805a3243 100644
--- a/Data/User/GameConfig/SB3J08.ini
+++ b/Data/User/GameConfig/SB3J08.ini
@@ -1,7 +1,7 @@
# SB3J08 - BASARA
[Core] Values set here will override the main dolphin settings.
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
-EmulationIssues = Audio synch issues during dialogues, otherwise perfect
+EmulationIssues =
EmulationStateId = 5
[OnFrame] Add memory patches to be applied every frame here.
[ActionReplay] Add action replay cheats here.
diff --git a/Data/User/GameConfig/SB3P08.ini b/Data/User/GameConfig/SB3P08.ini
index e6d3b168ea..bd1677f5eb 100644
--- a/Data/User/GameConfig/SB3P08.ini
+++ b/Data/User/GameConfig/SB3P08.ini
@@ -1,7 +1,7 @@
# SB3P08 - BASARA
[Core] Values set here will override the main dolphin settings.
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
-EmulationIssues = Audio synch issues during dialogues, otherwise perfect
+EmulationIssues =
EmulationStateId = 5
[OnFrame] Add memory patches to be applied every frame here.
[ActionReplay] Add action replay cheats here.
diff --git a/Data/User/GameConfig/SLWE41.ini b/Data/User/GameConfig/SLWE41.ini
new file mode 100644
index 0000000000..8c6c850c01
--- /dev/null
+++ b/Data/User/GameConfig/SLWE41.ini
@@ -0,0 +1,18 @@
+# SLWE41 - Where's Waldo? The Fantastic Journey
+[Core] Values set here will override the main dolphin settings.
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 4
+EmulationIssues = Needs Real Xfb for the pointer to appear.
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
+[Video_Settings]
+UseXFB = True
+UseRealXFB = True
diff --git a/Data/User/GameConfig/SVBE52.ini b/Data/User/GameConfig/SVBE52.ini
new file mode 100644
index 0000000000..30756bcb27
--- /dev/null
+++ b/Data/User/GameConfig/SVBE52.ini
@@ -0,0 +1,17 @@
+# SVBE52 - Battleship
+[Core] Values set here will override the main dolphin settings.
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 4
+EmulationIssues =
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
+[Video_Settings]
+SafeTextureCacheColorSamples = 0
diff --git a/Data/User/GameConfig/SVBP52.ini b/Data/User/GameConfig/SVBP52.ini
new file mode 100644
index 0000000000..8095983a48
--- /dev/null
+++ b/Data/User/GameConfig/SVBP52.ini
@@ -0,0 +1,17 @@
+# SVBP52 - Battleship
+[Core] Values set here will override the main dolphin settings.
+[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
+EmulationStateId = 4
+EmulationIssues =
+[OnFrame] Add memory patches to be applied every frame here.
+[ActionReplay] Add action replay cheats here.
+[Video]
+ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
+[Video_Settings]
+SafeTextureCacheColorSamples = 0
diff --git a/Data/User/GameConfig/W8CEXS.ini b/Data/User/GameConfig/W8CEXS.ini
index dcaeed3473..7607ca4e5f 100644
--- a/Data/User/GameConfig/W8CEXS.ini
+++ b/Data/User/GameConfig/W8CEXS.ini
@@ -1,10 +1,15 @@
# W8CEXS - BIT.TRIP CORE
[Core] Values set here will override the main dolphin settings.
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
-EmulationStateId = 1
-EmulationIssues = Requires a Wii save game to boot
+EmulationStateId = 4
+EmulationIssues =
[OnFrame] Add memory patches to be applied every frame here.
[ActionReplay] Add action replay cheats here.
[Video]
ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
[Gecko]
diff --git a/Data/User/GameConfig/WILETL.ini b/Data/User/GameConfig/WILETL.ini
index e8823e2ae1..0be2cca3c9 100644
--- a/Data/User/GameConfig/WILETL.ini
+++ b/Data/User/GameConfig/WILETL.ini
@@ -2,8 +2,14 @@
[Core] Values set here will override the main dolphin settings.
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
EmulationIssues =
-EmulationStateId = 1
+EmulationStateId = 4
[OnFrame] Add memory patches to be applied every frame here.
[ActionReplay] Add action replay cheats here.
[Video]
ProjectionHack = 0
+PH_SZNear = 0
+PH_SZFar = 0
+PH_ExtraParam = 0
+PH_ZNear =
+PH_ZFar =
+[Gecko]
diff --git a/Externals/soundtouch/STTypes.h b/Externals/soundtouch/STTypes.h
index 9855939119..39bc68bd69 100644
--- a/Externals/soundtouch/STTypes.h
+++ b/Externals/soundtouch/STTypes.h
@@ -80,7 +80,7 @@ namespace soundtouch
#undef SOUNDTOUCH_INTEGER_SAMPLES
#undef SOUNDTOUCH_FLOAT_SAMPLES
- #if (defined(__SOFTFP__))
+ #if (defined(ANDROID) && defined(__SOFTFP__))
// For Android compilation: Force use of Integer samples in case that
// compilation uses soft-floating point emulation - soft-fp is way too slow
#undef SOUNDTOUCH_FLOAT_SAMPLES
diff --git a/Source/Android/.idea/.name b/Source/Android/.idea/.name
new file mode 100644
index 0000000000..1429c13e57
--- /dev/null
+++ b/Source/Android/.idea/.name
@@ -0,0 +1 @@
+Android
\ No newline at end of file
diff --git a/Source/Android/.idea/compiler.xml b/Source/Android/.idea/compiler.xml
new file mode 100644
index 0000000000..217af471a9
--- /dev/null
+++ b/Source/Android/.idea/compiler.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Android/.idea/copyright/profiles_settings.xml b/Source/Android/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000000..3572571ad8
--- /dev/null
+++ b/Source/Android/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Android/.idea/encodings.xml b/Source/Android/.idea/encodings.xml
new file mode 100644
index 0000000000..e206d70d85
--- /dev/null
+++ b/Source/Android/.idea/encodings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Source/Android/.idea/libraries/dexedLibs.xml b/Source/Android/.idea/libraries/dexedLibs.xml
new file mode 100644
index 0000000000..d8e5061380
--- /dev/null
+++ b/Source/Android/.idea/libraries/dexedLibs.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Android/.idea/misc.xml b/Source/Android/.idea/misc.xml
new file mode 100644
index 0000000000..4304d8b8c8
--- /dev/null
+++ b/Source/Android/.idea/misc.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Android 4.2.2
+
+
+
+
+
+
+
+
+
diff --git a/Source/Android/.idea/modules.xml b/Source/Android/.idea/modules.xml
new file mode 100644
index 0000000000..e28a283f98
--- /dev/null
+++ b/Source/Android/.idea/modules.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Android/.idea/scopes/scope_settings.xml b/Source/Android/.idea/scopes/scope_settings.xml
new file mode 100644
index 0000000000..922003b843
--- /dev/null
+++ b/Source/Android/.idea/scopes/scope_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Android/.idea/vcs.xml b/Source/Android/.idea/vcs.xml
new file mode 100644
index 0000000000..def6a6a184
--- /dev/null
+++ b/Source/Android/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Source/Android/.idea/workspace.xml b/Source/Android/.idea/workspace.xml
new file mode 100644
index 0000000000..2a518c17f3
--- /dev/null
+++ b/Source/Android/.idea/workspace.xml
@@ -0,0 +1,764 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ android-17
+
+
+
+
+
+ Nexus 4
+ @android:style/Theme.Holo
+
+
+
+
+ Nexus 4
+ @android:style/Theme.Holo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Abstraction issues
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost
+ 5050
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+ 1368695084085
+ 1368695084085
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Android/Android.iml b/Source/Android/Android.iml
new file mode 100644
index 0000000000..5f8bb57f26
--- /dev/null
+++ b/Source/Android/Android.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Android/AndroidManifest.xml b/Source/Android/AndroidManifest.xml
index 82573aa8aa..3b4d735b37 100644
--- a/Source/Android/AndroidManifest.xml
+++ b/Source/Android/AndroidManifest.xml
@@ -1,8 +1,8 @@
+ android:versionCode="5"
+ android:versionName="0.5" >
@@ -28,15 +28,16 @@
-
+
+
diff --git a/Source/Android/res/layout/prefs.xml b/Source/Android/res/layout/prefs.xml
new file mode 100644
index 0000000000..bceb581c36
--- /dev/null
+++ b/Source/Android/res/layout/prefs.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Android/res/values/prefvalues.xml b/Source/Android/res/values/prefvalues.xml
new file mode 100644
index 0000000000..77354f76a4
--- /dev/null
+++ b/Source/Android/res/values/prefvalues.xml
@@ -0,0 +1,22 @@
+
+
+
+ - Interpreter
+ - ARM JIT Recompiler
+
+
+
+ - 0
+ - 3
+
+
+
+ - Software Renderer
+ - OpenGL
+
+
+
+ - Software Renderer
+ - OGL
+
+
\ No newline at end of file
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java
index db647723ad..bee3e5fcca 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java
@@ -1,13 +1,5 @@
package org.dolphinemu.dolphinemu;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import net.simonvt.menudrawer.MenuDrawer;
-
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -18,6 +10,8 @@ import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManager;
+import java.io.*;
+
public class DolphinEmulator extends Activity
{
static private NativeGLSurfaceView GLview = null;
@@ -25,7 +19,7 @@ public class DolphinEmulator extends Activity
private float screenWidth;
private float screenHeight;
-
+
public static native void onTouchEvent(int Action, float X, float Y);
static
@@ -143,7 +137,7 @@ public class DolphinEmulator extends Activity
String FileName = data.getStringExtra("Select");
GLview = new NativeGLSurfaceView(this);
- //this.getWindow().setUiOptions(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN, View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
+ this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
GLview.SetDimensions(screenWidth, screenHeight);
GLview.SetFileName(FileName);
setContentView(GLview);
@@ -169,7 +163,7 @@ public class DolphinEmulator extends Activity
return false;
}
- public boolean overrideKeys()
+ public boolean overrideKeys()
{
return false;
}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/FolderBrowser.java b/Source/Android/src/org/dolphinemu/dolphinemu/FolderBrowser.java
index 68203413b7..0ff58cdb39 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/FolderBrowser.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/FolderBrowser.java
@@ -1,29 +1,19 @@
package org.dolphinemu.dolphinemu;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import net.simonvt.menudrawer.MenuDrawer;
-
import android.app.Activity;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
-import android.view.Gravity;
-import android.view.LayoutInflater;
+import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemLongClickListener;
-import android.widget.BaseAdapter;
-import android.widget.LinearLayout;
import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.Toast;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
public class FolderBrowser extends ListActivity {
private GameListAdapter adapter;
@@ -59,8 +49,8 @@ public class FolderBrowser extends ListActivity {
Collections.sort(dir);
Collections.sort(fls);
dir.addAll(fls);
- if (!f.getName().equalsIgnoreCase("sdcard"))
- dir.add(0, new GameListItem(getApplicationContext(), "..", "Parent Directory", f.getParent()));
+ if (!f.getPath().equalsIgnoreCase("/"))
+ dir.add(0, new GameListItem(getApplicationContext(), "..", "Parent Directory", f.getParent()));
adapter = new GameListAdapter(this,R.layout.folderbrowser,dir);
this.setListAdapter(adapter);
@@ -68,7 +58,6 @@ public class FolderBrowser extends ListActivity {
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
- // TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
GameListItem o = adapter.getItem(position);
if(o.getData().equalsIgnoreCase("folder")||o.getData().equalsIgnoreCase("parent directory")){
@@ -87,12 +76,18 @@ public class FolderBrowser extends ListActivity {
Fill(currentDir);
}
@Override
- public void onBackPressed() {
+ public boolean onCreateOptionsMenu(Menu menu)
+ {
+ menu.add("Add current folder");
+ return true;
+ }
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
Intent intent = new Intent();
intent.putExtra("Select", currentDir.getPath());
setResult(Activity.RESULT_OK, intent);
-
- this.finish();
- super.onBackPressed();
+
+ this.finish();
+ return true;
}
}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/GameListView.java b/Source/Android/src/org/dolphinemu/dolphinemu/GameListView.java
index d585ead372..314e8e0ae5 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/GameListView.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/GameListView.java
@@ -1,85 +1,79 @@
package org.dolphinemu.dolphinemu;
+import android.app.Activity;
+import android.app.ListActivity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.Toast;
+import net.simonvt.menudrawer.MenuDrawer;
+
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import net.simonvt.menudrawer.MenuDrawer;
-
-import android.app.Activity;
-import android.app.ListActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Environment;
-import android.util.DisplayMetrics;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.Surface;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.Toast;
-
public class GameListView extends ListActivity {
private GameListAdapter adapter;
- private static File currentDir = null;
private MenuDrawer mDrawer;
private SideMenuAdapter mAdapter;
- private ListView mList;
private static GameListView me;
public static native String GetConfig(String Key, String Value, String Default);
public static native void SetConfig(String Key, String Value, String Default);
+
+ enum keyTypes {TYPE_STRING, TYPE_BOOL};
- private void Fill(File f)
+ private void Fill()
{
- File[]dirs = f.listFiles();
+
+
this.setTitle("Game List");
- Listdir = new ArrayList();
Listfls = new ArrayList();
-
- try
+ String Directories = GetConfig("General", "GCMPathes", "0");
+ int intDirectories = Integer.parseInt(Directories);
+ for (int a = 0; a < intDirectories; ++a)
{
- for(File ff: dirs)
+ String BrowseDir = GetConfig("General", "GCMPath" + Integer.toString(a), "");
+ File currentDir = new File(BrowseDir);
+ File[]dirs = currentDir.listFiles();
+ try
{
- if (ff.getName().charAt(0) != '.')
- if(!ff.isDirectory())
- if (ff.getName().toLowerCase().contains(".gcm") ||
- ff.getName().toLowerCase().contains(".iso") ||
- ff.getName().toLowerCase().contains(".wbfs") ||
- ff.getName().toLowerCase().contains(".gcz") ||
- ff.getName().toLowerCase().contains(".dol") ||
- ff.getName().toLowerCase().contains(".elf"))
- fls.add(new GameListItem(getApplicationContext(), ff.getName(),"File Size: "+ff.length(),ff.getAbsolutePath()));
- }
- }
- catch(Exception e)
- {
- }
-
- Collections.sort(dir);
- Collections.sort(fls);
- dir.addAll(fls);
-
- adapter = new GameListAdapter(this,R.layout.main,dir);
- this.setListAdapter(adapter);
+ for(File ff: dirs)
+ {
+ if (ff.getName().charAt(0) != '.')
+ if(!ff.isDirectory())
+ if (ff.getName().toLowerCase().contains(".gcm") ||
+ ff.getName().toLowerCase().contains(".iso") ||
+ ff.getName().toLowerCase().contains(".wbfs") ||
+ ff.getName().toLowerCase().contains(".gcz") ||
+ ff.getName().toLowerCase().contains(".dol") ||
+ ff.getName().toLowerCase().contains(".elf") ||
+ ff.getName().toLowerCase().contains(".dff"))
+ fls.add(new GameListItem(getApplicationContext(), ff.getName(),"File Size: "+ff.length(),ff.getAbsolutePath()));
+ }
+ }
+ catch(Exception ignored)
+ {
+ }
+ }
+ Collections.sort(fls);
+
+ adapter = new GameListAdapter(this,R.layout.main, fls);
+ this.setListAdapter(adapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
- // TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
GameListItem o = adapter.getItem(position);
- if(o.getData().equalsIgnoreCase("folder")||o.getData().equalsIgnoreCase("parent directory")){
- }
- else
- {
+ if(!(o.getData().equalsIgnoreCase("folder")||o.getData().equalsIgnoreCase("parent directory")))
+ {
onFileClick(o.getPath());
}
}
@@ -98,17 +92,67 @@ public class GameListView extends ListActivity {
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
-
- if (resultCode == Activity.RESULT_OK)
- {
- String FileName = data.getStringExtra("Select");
- Toast.makeText(this, "Folder Selected: " + FileName, Toast.LENGTH_SHORT).show();
- SetConfig("General", "GCMPathes", "1");
- SetConfig("General", "GCMPaths0", FileName);
-
- currentDir = new File(FileName);
- Fill(currentDir);
- }
+
+ switch (requestCode)
+ {
+ // Browse
+ case 1:
+ if (resultCode == Activity.RESULT_OK)
+ {
+ String FileName = data.getStringExtra("Select");
+ Toast.makeText(this, "Folder Selected: " + FileName, Toast.LENGTH_SHORT).show();
+ String Directories = GetConfig("General", "GCMPathes", "0");
+ int intDirectories = Integer.parseInt(Directories);
+ Directories = Integer.toString(intDirectories + 1);
+ SetConfig("General", "GCMPathes", Directories);
+ SetConfig("General", "GCMPath" + Integer.toString(intDirectories), FileName);
+
+ Fill();
+ }
+ break;
+ // Settings
+ case 2:
+
+ String Keys[] = {
+ "cpupref",
+ "dualcorepref",
+ "gpupref",
+ };
+ String ConfigKeys[] = {
+ "Core-CPUCore",
+ "Core-CPUThread",
+ "Core-GFXBackend",
+ };
+
+ keyTypes KeysTypes[] = {
+ keyTypes.TYPE_STRING,
+ keyTypes.TYPE_BOOL,
+ keyTypes.TYPE_STRING,
+ };
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+
+ // Set our preferences here
+ for (int a = 0; a < Keys.length; ++a)
+ {
+ String ConfigValues[] = ConfigKeys[a].split("-");
+ String Key = ConfigValues[0];
+ String Value = ConfigValues[1];
+
+ switch(KeysTypes[a])
+ {
+ case TYPE_STRING:
+ String strPref = prefs.getString(Keys[a], "");
+ SetConfig(Key, Value, strPref);
+ break;
+ case TYPE_BOOL:
+ boolean boolPref = prefs.getBoolean(Keys[a], true);
+ SetConfig(Key, Value, boolPref ? "True" : "False");
+ break;
+ }
+
+ }
+ break;
+ }
}
@Override
@@ -119,15 +163,14 @@ public class GameListView extends ListActivity {
mDrawer = MenuDrawer.attach(this, MenuDrawer.MENU_DRAG_CONTENT);
- String BrowseDir = GetConfig("General", "GCMPaths0", "");
- if(currentDir == null)
- currentDir = new File(BrowseDir);
- Fill(currentDir);
+
+ Fill();
Listdir = new ArrayList();
dir.add(new SideMenuItem("Browse Folder", 0));
+ dir.add(new SideMenuItem("Settings", 1));
- mList = new ListView(this);
+ ListView mList = new ListView(this);
mAdapter = new SideMenuAdapter(this,R.layout.sidemenu,dir);
mList.setAdapter(mAdapter);
mList.setOnItemClickListener(mItemClickListener);
@@ -145,6 +188,11 @@ public class GameListView extends ListActivity {
Intent ListIntent = new Intent(me, FolderBrowser.class);
startActivityForResult(ListIntent, 1);
break;
+ case 1:
+ Toast.makeText(me, "Loading up settings", Toast.LENGTH_SHORT).show();
+ Intent SettingIntent = new Intent(me, PrefsActivity.class);
+ startActivityForResult(SettingIntent, 2);
+ break;
default:
break;
}
@@ -157,25 +205,18 @@ public class GameListView extends ListActivity {
mDrawer.setContentView(layoutResID);
onContentChanged();
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- mDrawer.toggleMenu();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onBackPressed() {
- final int drawerState = mDrawer.getDrawerState();
- if (drawerState == MenuDrawer.STATE_OPEN || drawerState == MenuDrawer.STATE_OPENING) {
- mDrawer.closeMenu();
- return;
- }
-
- super.onBackPressed();
- }
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (event.getAction() == KeyEvent.KEYCODE_MENU|| event.getAction() == KeyEvent.KEYCODE_BACK) {
+ final int drawerState = mDrawer.getDrawerState();
+ if (drawerState == MenuDrawer.STATE_OPEN || drawerState == MenuDrawer.STATE_OPENING) {
+ mDrawer.closeMenu();
+ return true;
+ }
+ mDrawer.openMenu();
+ return true;
+ }
+ return false;
+ }
}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/PrefsActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/PrefsActivity.java
new file mode 100644
index 0000000000..e12e37c10a
--- /dev/null
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/PrefsActivity.java
@@ -0,0 +1,40 @@
+package org.dolphinemu.dolphinemu;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
+
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+public class PrefsActivity extends PreferenceActivity {
+
+ public class PrefsFragment extends PreferenceFragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.layout.prefs);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getFragmentManager().beginTransaction().replace(android.R.id.content,
+ new PrefsFragment()).commit();
+ }
+ @Override
+ public void onBackPressed() {
+ Intent intent = new Intent();
+ setResult(Activity.RESULT_OK, intent);
+ this.finish();
+ super.onBackPressed();
+ }
+}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/SideMenuItem.java b/Source/Android/src/org/dolphinemu/dolphinemu/SideMenuItem.java
index 80f3eaec64..e24842bed1 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/SideMenuItem.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/SideMenuItem.java
@@ -1,5 +1,11 @@
package org.dolphinemu.dolphinemu;
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
public class SideMenuItem implements Comparable{
private String m_name;
private int m_id;
diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp
index b1e601dfe7..1c6467b801 100644
--- a/Source/Core/AudioCommon/Src/OpenALStream.cpp
+++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp
@@ -97,7 +97,7 @@ void OpenALStream::SetVolume(int volume)
fVolume = (float)volume / 100.0f;
if (uiSource)
- alSourcef(uiSource, AL_GAIN, fVolume);
+ alSourcef(uiSource, AL_GAIN, fVolume);
}
void OpenALStream::Update()
@@ -124,6 +124,17 @@ void OpenALStream::SoundLoop()
{
Common::SetCurrentThreadName("Audio thread - openal");
+ bool surround_capable = Core::g_CoreStartupParameter.bDPL2Decoder;
+#if defined(__APPLE__)
+ bool float32_capable = false;
+ const ALenum AL_FORMAT_STEREO_FLOAT32 = 0;
+ // OSX does not have the alext AL_FORMAT_51CHN32 yet.
+ surround_capable = false;
+ const ALenum AL_FORMAT_51CHN32 = 0;
+#else
+ bool float32_capable = true;
+#endif
+
u32 ulFrequency = m_mixer->GetSampleRate();
numBuffers = Core::g_CoreStartupParameter.iLatency + 2; // OpenAL requires a minimum of two buffers
@@ -136,22 +147,20 @@ void OpenALStream::SoundLoop()
alGenSources(1, &uiSource);
// Short Silence
- memset(sampleBuffer, 0, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * numBuffers);
- memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4);
+ memset(sampleBuffer, 0, OAL_MAX_SAMPLES * numBuffers * FRAME_SURROUND_FLOAT);
+ memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * FRAME_STEREO_SHORT);
for (int i = 0; i < numBuffers; i++)
{
-#if !defined(__APPLE__)
- if (Core::g_CoreStartupParameter.bDPL2Decoder)
- alBufferData(uiBuffers[i], AL_FORMAT_51CHN32, sampleBuffer, 4 * SIZE_FLOAT * SURROUND_CHANNELS, ulFrequency);
+ if (surround_capable)
+ alBufferData(uiBuffers[i], AL_FORMAT_51CHN32, sampleBuffer, 4 * FRAME_SURROUND_FLOAT, ulFrequency);
else
-#endif
- alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, 4 * 2 * 2, ulFrequency);
+ alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, 4 * FRAME_STEREO_SHORT, ulFrequency);
}
alSourceQueueBuffers(uiSource, numBuffers, uiBuffers);
alSourcePlay(uiSource);
-
+
// Set the default sound volume as saved in the config file.
- alSourcef(uiSource, AL_GAIN, fVolume);
+ alSourcef(uiSource, AL_GAIN, fVolume);
// TODO: Error handling
//ALenum err = alGetError();
@@ -170,14 +179,7 @@ void OpenALStream::SoundLoop()
soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28);
soundTouch.setSetting(SETTING_OVERLAP_MS, 12);
- bool surround_capable = Core::g_CoreStartupParameter.bDPL2Decoder;
-#if defined(__APPLE__)
- bool float32_capable = false;
-#else
- bool float32_capable = true;
-#endif
-
- while (!threadData)
+ while (!threadData)
{
// num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD.
const u32 stereo_16_bit_size = 4;
@@ -193,12 +195,9 @@ void OpenALStream::SoundLoop()
numSamples = m_mixer->Mix(realtimeBuffer, numSamples);
// Convert the samples from short to float
- float dest[OAL_MAX_SAMPLES * 2 * 2 * OAL_MAX_BUFFERS];
- for (u32 i = 0; i < numSamples; ++i)
- {
- dest[i * 2 + 0] = (float)realtimeBuffer[i * 2 + 0] / (1 << 16);
- dest[i * 2 + 1] = (float)realtimeBuffer[i * 2 + 1] / (1 << 16);
- }
+ float dest[OAL_MAX_SAMPLES * STEREO_CHANNELS];
+ for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
+ dest[i] = (float)realtimeBuffer[i] / (1 << 16);
soundTouch.putSamples(dest, numSamples);
@@ -230,101 +229,94 @@ void OpenALStream::SoundLoop()
}
}
- unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * OAL_MAX_BUFFERS);
+ unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * numBuffers);
- if (nSamples > minSamples)
+ if (nSamples < minSamples)
+ continue;
+
+ // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
+ if (iBuffersFilled == 0)
{
- // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
- if (iBuffersFilled == 0)
- {
- alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp);
- ALenum err = alGetError();
- if (err != 0)
- {
- ERROR_LOG(AUDIO, "Error unqueuing buffers: %08x", err);
- }
- }
-#if defined(__APPLE__)
- // OSX does not have the alext AL_FORMAT_51CHN32 yet.
- surround_capable = false;
-#else
- if (surround_capable)
- {
- float dpl2[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
- dpl2decode(sampleBuffer, nSamples, dpl2);
-
- alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN32, dpl2, nSamples * SIZE_FLOAT * SURROUND_CHANNELS, ulFrequency);
- ALenum err = alGetError();
- if (err == AL_INVALID_ENUM)
- {
- // 5.1 is not supported by the host, fallback to stereo
- WARN_LOG(AUDIO, "Unable to set 5.1 surround mode. Updating OpenAL Soft might fix this issue.");
- surround_capable = false;
- }
- else if (err != 0)
- {
- ERROR_LOG(AUDIO, "Error occurred while buffering data: %08x", err);
- }
- }
-#endif
- if (!surround_capable)
- {
-#if !defined(__APPLE__)
- if (float32_capable)
- {
- alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * 4 * 2, ulFrequency);
- ALenum err = alGetError();
- if (err == AL_INVALID_ENUM)
- {
- float32_capable = false;
- }
- else if (err != 0)
- {
- ERROR_LOG(AUDIO, "Error occurred while buffering float32 data: %08x", err);
- }
- }
-#endif
- if (!float32_capable)
- {
- // Convert the samples from float to short
- short stereo[OAL_MAX_SAMPLES * 2 * 2 * OAL_MAX_BUFFERS];
- for (u32 i = 0; i < nSamples; ++i)
- {
- stereo[i * 2 + 0] = (short)((float)sampleBuffer[i * 2 + 0] * (1 << 16));
- stereo[i * 2 + 1] = (short)((float)sampleBuffer[i * 2 + 1] * (1 << 16));
- }
- alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, stereo, nSamples * 2 * 2, ulFrequency);
- }
- }
-
- alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]);
+ alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp);
ALenum err = alGetError();
if (err != 0)
{
- ERROR_LOG(AUDIO, "Error queuing buffers: %08x", err);
+ ERROR_LOG(AUDIO, "Error unqueuing buffers: %08x", err);
}
- iBuffersFilled++;
+ }
- if (iBuffersFilled == numBuffers)
+ if (surround_capable)
+ {
+ float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS];
+ dpl2decode(sampleBuffer, nSamples, dpl2);
+ alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_51CHN32, dpl2, nSamples * FRAME_SURROUND_FLOAT, ulFrequency);
+ ALenum err = alGetError();
+ if (err == AL_INVALID_ENUM)
{
- alSourcePlay(uiSource);
- err = alGetError();
- if (err != 0)
+ // 5.1 is not supported by the host, fallback to stereo
+ WARN_LOG(AUDIO, "Unable to set 5.1 surround mode. Updating OpenAL Soft might fix this issue.");
+ surround_capable = false;
+ }
+ else if (err != 0)
+ {
+ ERROR_LOG(AUDIO, "Error occurred while buffering data: %08x", err);
+ }
+ }
+
+ else
+ {
+ if (float32_capable)
+ {
+ alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * FRAME_STEREO_FLOAT, ulFrequency);
+ ALenum err = alGetError();
+ if (err == AL_INVALID_ENUM)
{
- ERROR_LOG(AUDIO, "Error occurred during playback: %08x", err);
+ float32_capable = false;
+ }
+ else if (err != 0)
+ {
+ ERROR_LOG(AUDIO, "Error occurred while buffering float32 data: %08x", err);
}
}
- alGetSourcei(uiSource, AL_SOURCE_STATE, &iState);
- if (iState != AL_PLAYING)
+ else
{
- // Buffer underrun occurred, resume playback
- alSourcePlay(uiSource);
- err = alGetError();
- if (err != 0)
- {
- ERROR_LOG(AUDIO, "Error occurred resuming playback: %08x", err);
- }
+ // Convert the samples from float to short
+ short stereo[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS];
+ for (u32 i = 0; i < nSamples * STEREO_CHANNELS; ++i)
+ stereo[i] = (short)((float)sampleBuffer[i] * (1 << 16));
+
+ alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, stereo, nSamples * FRAME_STEREO_SHORT, ulFrequency);
+ }
+ }
+
+ alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]);
+ ALenum err = alGetError();
+ if (err != 0)
+ {
+ ERROR_LOG(AUDIO, "Error queuing buffers: %08x", err);
+ }
+ iBuffersFilled++;
+
+ if (iBuffersFilled == numBuffers)
+ {
+ alSourcePlay(uiSource);
+ err = alGetError();
+ if (err != 0)
+ {
+ ERROR_LOG(AUDIO, "Error occurred during playback: %08x", err);
+ }
+ }
+
+ alGetSourcei(uiSource, AL_SOURCE_STATE, &iState);
+ if (iState != AL_PLAYING)
+ {
+ // Buffer underrun occurred, resume playback
+ alSourcePlay(uiSource);
+ err = alGetError();
+ if (err != 0)
+ {
+ ERROR_LOG(AUDIO, "Error occurred resuming playback: %08x", err);
}
}
}
diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h
index 42371db045..24217169bd 100644
--- a/Source/Core/AudioCommon/Src/OpenALStream.h
+++ b/Source/Core/AudioCommon/Src/OpenALStream.h
@@ -30,11 +30,16 @@
#include
// 16 bit Stereo
-#define SFX_MAX_SOURCE 1
-#define OAL_MAX_BUFFERS 32
-#define OAL_MAX_SAMPLES 256
-#define SURROUND_CHANNELS 6 // number of channels in surround mode
-#define SIZE_FLOAT 4 // size of a float in bytes
+#define SFX_MAX_SOURCE 1
+#define OAL_MAX_BUFFERS 32
+#define OAL_MAX_SAMPLES 256
+#define STEREO_CHANNELS 2
+#define SURROUND_CHANNELS 6 // number of channels in surround mode
+#define SIZE_SHORT 2
+#define SIZE_FLOAT 4 // size of a float in bytes
+#define FRAME_STEREO_SHORT STEREO_CHANNELS * SIZE_SHORT
+#define FRAME_STEREO_FLOAT STEREO_CHANNELS * SIZE_FLOAT
+#define FRAME_SURROUND_FLOAT SURROUND_CHANNELS * SIZE_FLOAT
#endif
class OpenALStream: public SoundStream
@@ -61,8 +66,8 @@ private:
std::thread thread;
Common::Event soundSyncEvent;
- short realtimeBuffer[OAL_MAX_SAMPLES * 2];
- soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
+ short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS];
+ soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
ALuint uiBuffers[OAL_MAX_BUFFERS];
ALuint uiSource;
ALfloat fVolume;
diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h
index 710c20955e..4321e6dba0 100644
--- a/Source/Core/Common/Src/CommonFuncs.h
+++ b/Source/Core/Common/Src/CommonFuncs.h
@@ -86,6 +86,45 @@ inline u64 _rotr64(u64 x, unsigned int shift){
#define unlink _unlink
#define snprintf _snprintf
#define vscprintf _vscprintf
+
+// Locale Cross-Compatibility
+ #define locale_t _locale_t
+ #define freelocale _free_locale
+ #define newlocale(mask, locale, base) _create_locale(mask, locale)
+
+ #define LC_GLOBAL_LOCALE ((locale_t)-1)
+ #define LC_ALL_MASK LC_ALL
+ #define LC_COLLATE_MASK LC_COLLATE
+ #define LC_CTYPE_MASK LC_CTYPE
+ #define LC_MONETARY_MASK LC_MONETARY
+ #define LC_NUMERIC_MASK LC_NUMERIC
+ #define LC_TIME_MASK LC_TIME
+
+ inline locale_t uselocale(locale_t new_locale)
+ {
+ // Retrieve the current per thread locale setting
+ bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE);
+
+ // Retrieve the current thread-specific locale
+ locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE;
+
+ if(new_locale == LC_GLOBAL_LOCALE)
+ {
+ // Restore the global locale
+ _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
+ }
+ else if(new_locale != NULL)
+ {
+ // Configure the thread to set the locale only for this thread
+ _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
+
+ // Set all locale categories
+ for(int i = LC_MIN; i <= LC_MAX; i++)
+ setlocale(i, new_locale->locinfo->lc_category[i].locale);
+ }
+
+ return old_locale;
+ }
// 64 bit offsets for windows
#define fseeko _fseeki64
diff --git a/Source/Core/Common/Src/MathUtil.cpp b/Source/Core/Common/Src/MathUtil.cpp
index 0e90328ee0..fc79a54ef0 100644
--- a/Source/Core/Common/Src/MathUtil.cpp
+++ b/Source/Core/Common/Src/MathUtil.cpp
@@ -13,61 +13,54 @@ namespace MathUtil
{
u32 ClassifyDouble(double dvalue)
-{
- // TODO: Optimize the below to be as fast as possible.
- IntDouble value;
- value.d = dvalue;
- u64 sign = value.i & DOUBLE_SIGN;
- u64 exp = value.i & DOUBLE_EXP;
- if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
- {
- // Nice normalized number.
- return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
- }
- else
- {
- u64 mantissa = value.i & DOUBLE_FRAC;
- if (mantissa)
- {
- if (exp)
- {
- return PPC_FPCLASS_QNAN;
- }
- else
- {
- // Denormalized number.
- return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
- }
- }
- else if (exp)
- {
- //Infinite
- return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
- }
- else
- {
- //Zero
- return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
- }
- }
-}
+ {
+ // TODO: Optimize the below to be as fast as possible.
+ u64 exp = *(u64*)(&dvalue) & DOUBLE_EXP;
+ if (exp != DOUBLE_ZERO && exp != DOUBLE_EXP)
+ {
+ // Nice normalized number.
+ return *(u64*)(&dvalue)&DOUBLE_SIGN ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
+ }
+ else
+ {
+ if (*(u64*)(&dvalue) & DOUBLE_FRAC)
+ {
+ if (exp)
+ {
+ return PPC_FPCLASS_QNAN;
+ }
+ else
+ {
+ // Denormalized number.
+ return *(u64*)(&dvalue)&DOUBLE_SIGN ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
+ }
+ }
+ else if (exp)
+ {
+ //Infinite
+ return *(u64*)(&dvalue)&DOUBLE_SIGN ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
+ }
+ else
+ {
+ //Zero
+ return *(u64*)(&dvalue)&DOUBLE_SIGN ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
+ }
+ }
+ }
+
u32 ClassifyFloat(float fvalue)
{
// TODO: Optimize the below to be as fast as possible.
- IntFloat value;
- value.f = fvalue;
- u32 sign = value.i & FLOAT_SIGN;
- u32 exp = value.i & FLOAT_EXP;
+ u32 exp = *(u32*)(&fvalue) & FLOAT_EXP;
if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
{
// Nice normalized number.
- return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
+ return *(u32*)(&fvalue) & FLOAT_SIGN ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
}
else
{
- u32 mantissa = value.i & FLOAT_FRAC;
- if (mantissa)
+ if (*(u32*)(&fvalue) & FLOAT_FRAC)
{
if (exp)
{
@@ -76,18 +69,18 @@ u32 ClassifyFloat(float fvalue)
else
{
// Denormalized number.
- return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
+ return *(u32*)(&fvalue) & FLOAT_SIGN ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
}
}
else if (exp)
{
// Infinite
- return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
+ return *(u32*)(&fvalue) & FLOAT_SIGN ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
}
else
{
//Zero
- return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
+ return *(u32*)(&fvalue) & FLOAT_SIGN ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
}
}
}
diff --git a/Source/Core/Common/Src/VideoBackendBase.cpp b/Source/Core/Common/Src/VideoBackendBase.cpp
index 8db4e2ff79..99bce01156 100644
--- a/Source/Core/Common/Src/VideoBackendBase.cpp
+++ b/Source/Core/Common/Src/VideoBackendBase.cpp
@@ -9,7 +9,7 @@
#include "../../../Plugins/Plugin_VideoDX9/Src/VideoBackend.h"
#include "../../../Plugins/Plugin_VideoDX11/Src/VideoBackend.h"
#endif
-#ifndef USE_GLES
+#if !defined(USE_GLES) || USE_GLES3
#include "../../../Plugins/Plugin_VideoOGL/Src/VideoBackend.h"
#endif
#include "../../../Plugins/Plugin_VideoSoftware/Src/VideoBackend.h"
@@ -45,7 +45,7 @@ void VideoBackend::PopulateList()
if (IsGteVista())
g_available_video_backends.push_back(backends[0] = new DX11::VideoBackend);
#endif
-#ifndef USE_GLES
+#if !defined(USE_GLES) || USE_GLES3
g_available_video_backends.push_back(backends[1] = new OGL::VideoBackend);
#endif
g_available_video_backends.push_back(backends[3] = new SW::VideoSoftware);
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 0fed2e0b8a..5474083132 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -111,6 +111,7 @@ set(SRCS Src/ActionReplay.cpp
Src/HW/SI.cpp
Src/HW/SI_DeviceAMBaseboard.cpp
Src/HW/SI_Device.cpp
+ Src/HW/SI_DeviceDanceMat.cpp
Src/HW/SI_DeviceGBA.cpp
Src/HW/SI_DeviceGCController.cpp
Src/HW/SI_DeviceGCSteeringWheel.cpp
@@ -216,7 +217,7 @@ endif()
set(LIBS bdisasm inputcommon videosoftware sfml-network)
-if(NOT USE_GLES)
+if(NOT USE_GLES OR USE_GLES3)
set(LIBS ${LIBS} videoogl)
endif()
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index 5d0d3b2754..a191d86282 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -298,6 +298,7 @@
+
@@ -498,6 +499,7 @@
+
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index c38d68c303..75c592a685 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -289,6 +289,9 @@
HW %28Flipper/Hollywood%29\SI - Serial Interface
+
+ HW %28Flipper/Hollywood%29\SI - Serial Interface
+
HW %28Flipper/Hollywood%29\VI - Video Interface
@@ -810,6 +813,9 @@
HW %28Flipper/Hollywood%29\SI - Serial Interface
+
+ HW %28Flipper/Hollywood%29\SI - Serial Interface
+
HW %28Flipper/Hollywood%29\SI - Serial Interface
diff --git a/Source/Core/Core/Src/BootManager.cpp b/Source/Core/Core/Src/BootManager.cpp
index f829f3f4d6..e4ce413926 100644
--- a/Source/Core/Core/Src/BootManager.cpp
+++ b/Source/Core/Core/Src/BootManager.cpp
@@ -60,6 +60,7 @@ bool BootCore(const std::string& _rFilename)
StartUp.m_BootType = SCoreStartupParameter::BOOT_ISO;
StartUp.m_strFilename = _rFilename;
SConfig::GetInstance().m_LastFilename = _rFilename;
+ SConfig::GetInstance().SaveSettings();
StartUp.bRunCompareClient = false;
StartUp.bRunCompareServer = false;
@@ -108,20 +109,6 @@ bool BootCore(const std::string& _rFilename)
game_ini.Get("Core", "HLE_BS2", &StartUp.bHLE_BS2, StartUp.bHLE_BS2);
VideoBackend::ActivateBackend(StartUp.m_strVideoBackend);
- if (Movie::IsPlayingInput() && Movie::IsConfigSaved())
- {
- StartUp.bCPUThread = Movie::IsDualCore();
- StartUp.bSkipIdle = Movie::IsSkipIdle();
- StartUp.bDSPHLE = Movie::IsDSPHLE();
- StartUp.bProgressive = Movie::IsProgressive();
- StartUp.bFastDiscSpeed = Movie::IsFastDiscSpeed();
- StartUp.iCPUCore = Movie::GetCPUMode();
- if (Movie::IsUsingMemcard() && Movie::IsStartingFromClearSave() && !StartUp.bWii)
- {
- if (File::Exists("Movie.raw"))
- File::Delete("Movie.raw");
- }
- }
// Wii settings
if (StartUp.bWii)
{
@@ -130,6 +117,22 @@ bool BootCore(const std::string& _rFilename)
}
}
+ // movie settings
+ if (Movie::IsPlayingInput() && Movie::IsConfigSaved())
+ {
+ StartUp.bCPUThread = Movie::IsDualCore();
+ StartUp.bSkipIdle = Movie::IsSkipIdle();
+ StartUp.bDSPHLE = Movie::IsDSPHLE();
+ StartUp.bProgressive = Movie::IsProgressive();
+ StartUp.bFastDiscSpeed = Movie::IsFastDiscSpeed();
+ StartUp.iCPUCore = Movie::GetCPUMode();
+ if (Movie::IsUsingMemcard() && Movie::IsStartingFromClearSave() && !StartUp.bWii)
+ {
+ if (File::Exists("Movie.raw"))
+ File::Delete("Movie.raw");
+ }
+ }
+
// Run the game
// Init the core
if (!Core::Init())
diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp
index 485c1ab259..2d4f566485 100644
--- a/Source/Core/Core/Src/ConfigManager.cpp
+++ b/Source/Core/Core/Src/ConfigManager.cpp
@@ -35,6 +35,7 @@ static const struct {
{ "ToggleFullscreen", 70 /* 'F' */, 2 /* wxMOD_CMD */ },
{ "Screenshot", 83 /* 'S' */, 2 /* wxMOD_CMD */ },
+ { "Exit", 0, 0 /* wxMOD_NONE */ },
{ "Wiimote1Connect", 49 /* '1' */, 2 /* wxMOD_CMD */ },
{ "Wiimote2Connect", 50 /* '2' */, 2 /* wxMOD_CMD */ },
@@ -57,6 +58,7 @@ static const struct {
{ "ToggleFullscreen", 13 /* WXK_RETURN */, 1 /* wxMOD_ALT */ },
{ "Screenshot", 348 /* WXK_F9 */, 0 /* wxMOD_NONE */ },
+ { "Exit", 0, 0 /* wxMOD_NONE */ },
{ "Wiimote1Connect", 344 /* WXK_F5 */, 1 /* wxMOD_ALT */ },
{ "Wiimote2Connect", 345 /* WXK_F6 */, 1 /* wxMOD_ALT */ },
@@ -81,6 +83,19 @@ static const struct {
{ "SaveStateSlot6", 345 /* WXK_F6 */, 4 /* wxMOD_SHIFT */ },
{ "SaveStateSlot7", 346 /* WXK_F7 */, 4 /* wxMOD_SHIFT */ },
{ "SaveStateSlot8", 347 /* WXK_F8 */, 4 /* wxMOD_SHIFT */ },
+
+ { "LoadLastState1", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState2", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState3", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState4", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState5", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState6", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState7", 0, 0 /* wxMOD_NONE */ },
+ { "LoadLastState8", 0, 0 /* wxMOD_NONE */ },
+
+ { "SaveFirstState", 0, 0 /* wxMOD_NONE */ },
+ { "UndoLoadState", 351 /* WXK_F12 */, 0 /* wxMOD_NONE */ },
+ { "UndoSaveState", 351 /* WXK_F12 */, 4 /* wxMOD_SHIFT */ },
};
SConfig::SConfig()
@@ -319,7 +334,7 @@ void SConfig::LoadSettings()
// Display
ini.Get("Display", "Fullscreen", &m_LocalCoreStartupParameter.bFullscreen, false);
- ini.Get("Display", "FullscreenResolution", &m_LocalCoreStartupParameter.strFullscreenResolution, "640x480");
+ ini.Get("Display", "FullscreenResolution", &m_LocalCoreStartupParameter.strFullscreenResolution, "Auto");
ini.Get("Display", "RenderToMain", &m_LocalCoreStartupParameter.bRenderToMain, false);
ini.Get("Display", "RenderWindowXPos", &m_LocalCoreStartupParameter.iRenderWindowXPos, -1);
ini.Get("Display", "RenderWindowYPos", &m_LocalCoreStartupParameter.iRenderWindowYPos, -1);
diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index 0d8752195f..268d474ae6 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -394,10 +394,10 @@ void EmuThread()
Wiimote::Initialize(g_pWindowHandle);
// Activate wiimotes which don't have source set to "None"
- for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
+ for (unsigned int i = 0; i != MAX_BBMOTES; ++i)
if (g_wiimote_sources[i])
- GetUsbPointer()->AccessWiiMote(i | 0x100)->
- Activate(true);
+ GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true);
+
}
// The hardware is initialized.
@@ -680,7 +680,8 @@ void UpdateTitle()
u32 Speed = DrawnVideo * (100 * 1000) / (VideoInterface::TargetRefreshRate * ElapseTime);
// Settings are shown the same for both extended and summary info
- std::string SSettings = StringFromFormat("%s %s", cpu_core_base->GetName(), _CoreParameter.bCPUThread ? "DC" : "SC");
+ std::string SSettings = StringFromFormat("%s %s | %s | %s", cpu_core_base->GetName(), _CoreParameter.bCPUThread ? "DC" : "SC",
+ g_video_backend->GetName().c_str(), _CoreParameter.bDSPHLE ? "HLE" : "LLE");
// Use extended or summary information. The summary information does not print the ticks data,
// that's more of a debugging interest, it can always be optional of course if someone is interested.
@@ -697,7 +698,7 @@ void UpdateTitle()
float TicksPercentage = (float)diff / (float)(SystemTimers::GetTicksPerSecond() / 1000000) * 100;
- std::string SFPS = StringFromFormat("FPS: %u - VPS: %u - SPEED: %u%%", FPS, VPS, Speed);
+ std::string SFPS = StringFromFormat("FPS: %u - VPS: %u - %u%%", FPS, VPS, Speed);
SFPS += StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
_CoreParameter.bSkipIdle ? "~" : "",
(int)(diff),
@@ -710,11 +711,11 @@ void UpdateTitle()
#else // Summary information
std::string SFPS;
if (Movie::IsPlayingInput())
- SFPS = StringFromFormat("VI: %u/%u - Frame: %u/%u - FPS: %u - VPS: %u - SPEED: %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_totalFrames, (u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount, FPS, VPS, Speed);
+ SFPS = StringFromFormat("VI: %u/%u - Frame: %u/%u - FPS: %u - VPS: %u - %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_totalFrames, (u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount, FPS, VPS, Speed);
else if (Movie::IsRecordingInput())
- SFPS = StringFromFormat("VI: %u - Frame: %u - FPS: %u - VPS: %u - SPEED: %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_currentInputCount, FPS, VPS, Speed);
+ SFPS = StringFromFormat("VI: %u - Frame: %u - FPS: %u - VPS: %u - %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_currentInputCount, FPS, VPS, Speed);
else
- SFPS = StringFromFormat("FPS: %u - VPS: %u - SPEED: %u%%", FPS, VPS, Speed);
+ SFPS = StringFromFormat("FPS: %u - VPS: %u - %u%%", FPS, VPS, Speed);
#endif
// This is our final "frame counter" string
diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h
index 9652b84618..6f2219e9f8 100644
--- a/Source/Core/Core/Src/CoreParameter.h
+++ b/Source/Core/Core/Src/CoreParameter.h
@@ -26,6 +26,7 @@ enum Hotkey
HK_FULLSCREEN,
HK_SCREENSHOT,
+ HK_EXIT,
HK_WIIMOTE1_CONNECT,
HK_WIIMOTE2_CONNECT,
@@ -50,6 +51,19 @@ enum Hotkey
HK_SAVE_STATE_SLOT_7,
HK_SAVE_STATE_SLOT_8,
+ HK_LOAD_LAST_STATE_1,
+ HK_LOAD_LAST_STATE_2,
+ HK_LOAD_LAST_STATE_3,
+ HK_LOAD_LAST_STATE_4,
+ HK_LOAD_LAST_STATE_5,
+ HK_LOAD_LAST_STATE_6,
+ HK_LOAD_LAST_STATE_7,
+ HK_LOAD_LAST_STATE_8,
+
+ HK_SAVE_FIRST_STATE,
+ HK_UNDO_LOAD_STATE,
+ HK_UNDO_SAVE_STATE,
+
NUM_HOTKEYS,
};
diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp
index af56ab25bb..06770aa375 100644
--- a/Source/Core/Core/Src/CoreTiming.cpp
+++ b/Source/Core/Core/Src/CoreTiming.cpp
@@ -170,7 +170,10 @@ void EventDoState(PointerWrap &p, BaseEvent* ev)
// we can't savestate ev->type directly because events might not get registered in the same order (or at all) every time.
// so, we savestate the event's type's name, and derive ev->type from that when loading.
- std::string name = event_types[ev->type].name;
+ std::string name;
+ if (p.GetMode() != PointerWrap::MODE_READ)
+ name = event_types[ev->type].name;
+
p.Do(name);
if (p.GetMode() == PointerWrap::MODE_READ)
{
diff --git a/Source/Core/Core/Src/DSP/DSPCore.cpp b/Source/Core/Core/Src/DSP/DSPCore.cpp
index 59e5063af6..64206b3ee0 100644
--- a/Source/Core/Core/Src/DSP/DSPCore.cpp
+++ b/Source/Core/Core/Src/DSP/DSPCore.cpp
@@ -137,6 +137,7 @@ bool DSPCore_Init(const char *irom_filename, const char *coef_filename,
{
g_dsp.step_counter = 0;
cyclesLeft = 0;
+ init_hax = false;
dspjit = NULL;
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
diff --git a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp
index 371bec572c..56e998d3c0 100644
--- a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp
+++ b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp
@@ -246,14 +246,9 @@ static void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size)
}
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
- g_dsp.iram_crc = DSPHost_CodeLoaded(g_dsp.cpu_ram + (addr & 0x0fffffff), size);
-
- NOTICE_LOG(DSPLLE, "*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)", addr, dsp_addr, g_dsp.iram_crc);
+ DSPHost_CodeLoaded((const u8*)g_dsp.iram + dsp_addr, size);
- if (dspjit)
- dspjit->ClearIRAM();
-
- DSPAnalyzer::Analyze();
+ NOTICE_LOG(DSPLLE, "*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)", addr, dsp_addr, g_dsp.iram_crc);
}
static void gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size)
diff --git a/Source/Core/Core/Src/DSP/DSPHost.h b/Source/Core/Core/Src/DSP/DSPHost.h
index 86033b0724..cef329a7ec 100644
--- a/Source/Core/Core/Src/DSP/DSPHost.h
+++ b/Source/Core/Core/Src/DSP/DSPHost.h
@@ -15,7 +15,7 @@ void DSPHost_WriteHostMemory(u8 value, u32 addr);
bool DSPHost_OnThread();
bool DSPHost_Wii();
void DSPHost_InterruptRequest();
-u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
+void DSPHost_CodeLoaded(const u8 *ptr, int size);
void DSPHost_UpdateDebugger();
#endif
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp
index 04cc3aa753..dbb185844e 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp
@@ -1563,6 +1563,7 @@ void DSPEmitter::lsrn(const UDSPInstruction opc)
FixupBranch noShift = J_CC(CC_Z);
//CL gets automatically masked with 0x3f on IA32/AMD64
//MOVZX(64, 16, RCX, R(RAX));
+ MOV(64, R(RCX), R(RAX));
//AND(16, R(RCX), Imm16(0x3f));
TEST(16, R(RAX), Imm16(0x40));
FixupBranch shiftLeft = J_CC(CC_Z);
diff --git a/Source/Core/Core/Src/GeckoCode.cpp b/Source/Core/Core/Src/GeckoCode.cpp
index f93bbd1b4c..c7127ef018 100644
--- a/Source/Core/Core/Src/GeckoCode.cpp
+++ b/Source/Core/Core/Src/GeckoCode.cpp
@@ -63,6 +63,38 @@ u32 GeckoCode::Code::GetAddress() const
return gcaddress + (use_po ? pointer_address : (base_address & 0xFE000000));
}
+// return true if a code exists
+bool GeckoCode::Exist(u32 address, u32 data)
+{
+ std::vector::const_iterator
+ codes_iter = codes.begin(),
+ codes_end = codes.end();
+ for (; codes_iter != codes_end; ++codes_iter)
+ {
+ if (codes_iter->address == address && codes_iter->data == data)
+ return true;
+ }
+ return false;
+}
+
+// return true if the code is identical
+bool GeckoCode::Compare(GeckoCode compare) const
+{
+ if (codes.size() != compare.codes.size())
+ return false;
+
+ int exist = 0;
+ std::vector::const_iterator
+ codes_iter = codes.begin(),
+ codes_end = codes.end();
+ for (; codes_iter != codes_end; ++codes_iter)
+ {
+ if (compare.Exist(codes_iter->address, codes_iter->data))
+ exist++;
+ }
+ return exist == codes.size();
+}
+
static std::mutex active_codes_lock;
// currently running code
diff --git a/Source/Core/Core/Src/GeckoCode.h b/Source/Core/Core/Src/GeckoCode.h
index 42ac941523..59da6fd091 100644
--- a/Source/Core/Core/Src/GeckoCode.h
+++ b/Source/Core/Core/Src/GeckoCode.h
@@ -66,6 +66,9 @@ namespace Gecko
std::vector notes;
bool enabled;
+
+ bool Compare(GeckoCode compare) const;
+ bool Exist(u32 address, u32 data);
};
void SetActiveCodes(const std::vector& gcodes);
diff --git a/Source/Core/Core/Src/HLE/HLE_Misc.cpp b/Source/Core/Core/Src/HLE/HLE_Misc.cpp
index a37fc44a97..c8323ca6c4 100644
--- a/Source/Core/Core/Src/HLE/HLE_Misc.cpp
+++ b/Source/Core/Core/Src/HLE/HLE_Misc.cpp
@@ -20,6 +20,7 @@
#include "PowerPC/SignatureDB.h"
#include "PowerPC/PPCSymbolDB.h"
#include "CommonPaths.h"
+#include "TextureCacheBase.h"
namespace HLE_Misc
{
@@ -310,6 +311,7 @@ void ExecuteDOL(u8* dolFile, u32 fileSize)
}
PowerPC::ppcState.iCache.Reset();
+ TextureCache::RequestInvalidateTextureCache();
CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = GetUsbPointer();
size_t size = s_Usb->m_WiiMotes.size();
diff --git a/Source/Core/Core/Src/HW/DSP.cpp b/Source/Core/Core/Src/HW/DSP.cpp
index 809128225e..3ef62e5aaa 100644
--- a/Source/Core/Core/Src/HW/DSP.cpp
+++ b/Source/Core/Core/Src/HW/DSP.cpp
@@ -687,12 +687,29 @@ void UpdateAudioDMA()
void Do_ARAM_DMA()
{
- g_dspState.DSPControl.DMAState = 1;
- CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
-
- // Force an early exception check on large transfers. Fixes RE2 audio.
- if (g_arDMA.Cnt.count > 2048 && g_arDMA.Cnt.count <= 6144)
+ if (g_arDMA.Cnt.count == 32)
+ {
+ // Beyond Good and Evil (GGEE41) sends count 32
+ // Lost Kingdoms 2 needs the exception check here in DSP HLE mode
+ GenerateDSPInterrupt(INT_ARAM);
CoreTiming::ForceExceptionCheck(100);
+ }
+ else
+ {
+ g_dspState.DSPControl.DMAState = 1;
+ CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
+
+ // Force an early exception check on large transfers. Fixes RE2 audio.
+ // NFS:HP2 (<= 6144)
+ // Viewtiful Joe (<= 6144)
+ // Sonic Mega Collection (> 2048)
+ // Paper Mario battles (> 32)
+ // Mario Super Baseball (> 32)
+ // Knockout Kings 2003 loading (> 32)
+ // WWE DOR (> 32)
+ if (g_arDMA.Cnt.count > 2048 && g_arDMA.Cnt.count <= 6144)
+ CoreTiming::ForceExceptionCheck(100);
+ }
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
if (g_arDMA.Cnt.dir)
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp
index f7387154b2..e28d5a32ae 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp
@@ -66,9 +66,8 @@ void CUCode_AX::LoadResamplingCoefficients()
WARN_LOG(DSPHLE, "Loading polyphase resampling coeffs from %s", filename.c_str());
- FILE* fp = fopen(filename.c_str(), "rb");
- fread(m_coeffs, 1, 0x1000, fp);
- fclose(fp);
+ File::IOFile fp(filename, "rb");
+ fp.ReadBytes(m_coeffs, 0x1000);
for (u32 i = 0; i < 0x800; ++i)
m_coeffs[i] = Common::swap16(m_coeffs[i]);
diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp
index 9349820450..26e7110d6e 100644
--- a/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp
+++ b/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp
@@ -4,6 +4,8 @@
#include "Common.h"
#include "Hash.h"
+#include "DSP/DSPAnalyzer.h"
+#include "DSP/DSPCore.h"
#include "DSP/DSPHost.h"
#include "DSPSymbols.h"
#include "DSPLLETools.h"
@@ -45,23 +47,23 @@ void DSPHost_InterruptRequest()
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
}
-u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
+void DSPHost_CodeLoaded(const u8 *ptr, int size)
{
- u32 ector_crc = HashEctor(ptr, size);
+ g_dsp.iram_crc = HashEctor(ptr, size);
#if defined(_DEBUG) || defined(DEBUGFAST)
- DumpDSPCode(ptr, size, ector_crc);
+ DumpDSPCode(ptr, size, g_dsp.iram_crc);
#endif
DSPSymbols::Clear();
// Auto load text file - if none just disassemble.
- NOTICE_LOG(DSPLLE, "ector_crc: %08x", ector_crc);
+ NOTICE_LOG(DSPLLE, "g_dsp.iram_crc: %08x", g_dsp.iram_crc);
DSPSymbols::Clear();
bool success = false;
- switch (ector_crc)
+ switch (g_dsp.iram_crc)
{
case 0x86840740: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Zelda.txt"); break;
case 0x42f64ac4: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Luigi.txt"); break;
@@ -86,7 +88,10 @@ u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
DSPHost_UpdateDebugger();
- return ector_crc;
+ if (dspjit)
+ dspjit->ClearIRAM();
+
+ DSPAnalyzer::Analyze();
}
void DSPHost_UpdateDebugger()
diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp
index df43441c03..d16af5f601 100644
--- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp
+++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp
@@ -16,6 +16,7 @@
#include "Core.h"
#include "DSPLLEGlobals.h" // Local
+#include "DSP/DSPHost.h"
#include "DSP/DSPInterpreter.h"
#include "DSP/DSPHWInterface.h"
#include "DSP/disassemble.h"
@@ -67,7 +68,6 @@ void DSPLLE::DoState(PointerWrap &p)
p.Do(g_dsp.reg_stack[i]);
}
- p.Do(g_dsp.iram_crc);
p.Do(g_dsp.step_counter);
p.Do(g_dsp.ifx_regs);
p.Do(g_dsp.mbox[0]);
@@ -75,8 +75,11 @@ void DSPLLE::DoState(PointerWrap &p)
UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
p.DoArray(g_dsp.iram, DSP_IRAM_SIZE);
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ DSPHost_CodeLoaded((const u8*)g_dsp.iram, DSP_IRAM_BYTE_SIZE);
p.DoArray(g_dsp.dram, DSP_DRAM_SIZE);
p.Do(cyclesLeft);
+ p.Do(init_hax);
p.Do(m_cycle_count);
bool prevInitMixer = m_InitMixer;
diff --git a/Source/Core/Core/Src/HW/DVDInterface.cpp b/Source/Core/Core/Src/HW/DVDInterface.cpp
index 03a856662e..0e77b2a443 100644
--- a/Source/Core/Core/Src/HW/DVDInterface.cpp
+++ b/Source/Core/Core/Src/HW/DVDInterface.cpp
@@ -530,6 +530,9 @@ void UpdateInterrupts()
{
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_DI, false);
}
+
+ // Required for Summoner: A Goddess Reborn
+ CoreTiming::ForceExceptionCheck(50);
}
void GenerateDIInterrupt(DI_InterruptType _DVDInterrupt)
diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp
index a13cdb4a2c..c51d3221e3 100644
--- a/Source/Core/Core/Src/HW/GCMemcard.cpp
+++ b/Source/Core/Core/Src/HW/GCMemcard.cpp
@@ -215,7 +215,12 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis)
}
mcdFile.Close();
+
+ initDirBatPointers();
+}
+void GCMemcard::initDirBatPointers()
+{
if (BE16(dir.UpdateCounter) > (BE16(dir_backup.UpdateCounter)))
{
CurrentDir = &dir;
@@ -1273,7 +1278,8 @@ bool GCMemcard::Format(bool sjis, u16 SizeMb)
GCMBlock b;
mc_data_blocks.push_back(b);
}
-
+
+ initDirBatPointers();
m_valid = true;
return Save();
diff --git a/Source/Core/Core/Src/HW/GCMemcard.h b/Source/Core/Core/Src/HW/GCMemcard.h
index a25d8daacb..215402dd10 100644
--- a/Source/Core/Core/Src/HW/GCMemcard.h
+++ b/Source/Core/Core/Src/HW/GCMemcard.h
@@ -171,6 +171,7 @@ private:
u32 ImportGciInternal(FILE* gcih, const char *inputFile, const std::string &outputFile);
static void FormatInternal(GCMC_Header &GCP);
+ void initDirBatPointers() ;
public:
GCMemcard(const char* fileName, bool forceCreation=false, bool sjis=false);
diff --git a/Source/Core/Core/Src/HW/MemmapFunctions.cpp b/Source/Core/Core/Src/HW/MemmapFunctions.cpp
index 39c852ec22..0e899079c5 100644
--- a/Source/Core/Core/Src/HW/MemmapFunctions.cpp
+++ b/Source/Core/Core/Src/HW/MemmapFunctions.cpp
@@ -598,9 +598,6 @@ union UPTE2
u32 Hex;
};
-u32 pagetable_base = 0;
-u32 pagetable_hashmask = 0;
-
void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite)
{
if (_bWrite)
@@ -644,8 +641,8 @@ void SDRUpdated()
{
return;
}
- pagetable_base = htaborg<<16;
- pagetable_hashmask = ((xx<<10)|0x3ff);
+ PowerPC::ppcState.pagetable_base = htaborg<<16;
+ PowerPC::ppcState.pagetable_hashmask = ((xx<<10)|0x3ff);
}
@@ -821,7 +818,7 @@ u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag)
// hash function no 1 "xor" .360
u32 hash1 = (VSID ^ page_index);
- u32 pteg_addr = ((hash1 & pagetable_hashmask) << 6) | pagetable_base;
+ u32 pteg_addr = ((hash1 & PowerPC::ppcState.pagetable_hashmask) << 6) | PowerPC::ppcState.pagetable_base;
// hash1
for (int i = 0; i < 8; i++)
@@ -856,7 +853,7 @@ u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag)
// hash function no 2 "not" .360
hash1 = ~hash1;
- pteg_addr = ((hash1 & pagetable_hashmask) << 6) | pagetable_base;
+ pteg_addr = ((hash1 & PowerPC::ppcState.pagetable_hashmask) << 6) | PowerPC::ppcState.pagetable_base;
for (int i = 0; i < 8; i++)
{
u32 pte = bswap(*(u32*)&pRAM[pteg_addr]);
diff --git a/Source/Core/Core/Src/HW/SI_Device.cpp b/Source/Core/Core/Src/HW/SI_Device.cpp
index baa144c83d..e9674bcab6 100644
--- a/Source/Core/Core/Src/HW/SI_Device.cpp
+++ b/Source/Core/Core/Src/HW/SI_Device.cpp
@@ -5,6 +5,7 @@
#include "SI_Device.h"
#include "SI_DeviceGCController.h"
#include "SI_DeviceGCSteeringWheel.h"
+#include "SI_DeviceDanceMat.h"
#include "SI_DeviceGBA.h"
#include "SI_DeviceAMBaseboard.h"
@@ -64,6 +65,10 @@ ISIDevice* SIDevice_Create(const SIDevices device, const int port_number)
return new CSIDevice_GCController(device, port_number);
break;
+ case SIDEVICE_DANCEMAT:
+ return new CSIDevice_DanceMat(device, port_number);
+ break;
+
case SIDEVICE_GC_STEERING:
return new CSIDevice_GCSteeringWheel(device, port_number);
break;
diff --git a/Source/Core/Core/Src/HW/SI_Device.h b/Source/Core/Core/Src/HW/SI_Device.h
index bf3e1fc506..62614656c7 100644
--- a/Source/Core/Core/Src/HW/SI_Device.h
+++ b/Source/Core/Core/Src/HW/SI_Device.h
@@ -34,6 +34,7 @@ enum TSIDevices
SI_GC_CONTROLLER = (SI_TYPE_GC | SI_GC_STANDARD),
SI_GC_KEYBOARD = (SI_TYPE_GC | 0x00200000),
SI_GC_STEERING = SI_TYPE_GC, // (shuffle2)I think the "chainsaw" is the same (Or else it's just standard)
+ SI_DANCEMAT = (SI_TYPE_GC | SI_GC_STANDARD | 0x00000300),
SI_AM_BASEBOARD = 0x10110800 // gets ORd with dipswitch state
};
@@ -49,6 +50,7 @@ enum SIDevices
SIDEVICE_GC_CONTROLLER,
SIDEVICE_GC_KEYBOARD,
SIDEVICE_GC_STEERING,
+ SIDEVICE_DANCEMAT,
SIDEVICE_GC_TARUKONGA,
SIDEVICE_AM_BASEBOARD
};
diff --git a/Source/Core/Core/Src/HW/SI_DeviceDanceMat.cpp b/Source/Core/Core/Src/HW/SI_DeviceDanceMat.cpp
new file mode 100644
index 0000000000..30237286e6
--- /dev/null
+++ b/Source/Core/Core/Src/HW/SI_DeviceDanceMat.cpp
@@ -0,0 +1,264 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include
+#include
+
+#include "SI.h"
+#include "SI_Device.h"
+#include "SI_DeviceDanceMat.h"
+
+#include "EXI_Device.h"
+#include "EXI_DeviceMic.h"
+
+#include "GCPad.h"
+
+#include "../Movie.h"
+
+#include "../CoreTiming.h"
+#include "SystemTimers.h"
+#include "ProcessorInterface.h"
+#include "../Core.h"
+
+// --- Dance mat gamecube controller ---
+CSIDevice_DanceMat::CSIDevice_DanceMat(SIDevices device, int _iDeviceNumber)
+ : ISIDevice(device, _iDeviceNumber)
+ , m_TButtonComboStart(0)
+ , m_TButtonCombo(0)
+ , m_LastButtonCombo(COMBO_NONE)
+{
+ memset(&m_Origin, 0, sizeof(SOrigin));
+ m_Origin.uCommand = CMD_ORIGIN;
+ m_Origin.uOriginStickX = 0x80; // center
+ m_Origin.uOriginStickY = 0x80;
+ m_Origin.uSubStickStickX = 0x80;
+ m_Origin.uSubStickStickY = 0x80;
+ m_Origin.uTrigger_L = 0x00;
+ m_Origin.uTrigger_R = 0x00;
+
+ // Dunno if we need to do this, game/lib should set it?
+ m_Mode = 0x03;
+}
+
+int CSIDevice_DanceMat::RunBuffer(u8* _pBuffer, int _iLength)
+{
+ // For debug logging only
+ ISIDevice::RunBuffer(_pBuffer, _iLength);
+
+ // Read the command
+ EBufferCommands command = static_cast(_pBuffer[3]);
+
+ // Handle it
+ switch (command)
+ {
+ case CMD_RESET:
+ *(u32*)&_pBuffer[0] = SI_DANCEMAT;
+ break;
+
+ case CMD_DIRECT:
+ {
+ INFO_LOG(SERIALINTERFACE, "PAD - Direct (Length: %d)", _iLength);
+ u32 high, low;
+ GetData(high, low);
+ for (int i = 0; i < (_iLength - 1) / 2; i++)
+ {
+ _pBuffer[0 + i] = (high >> (i * 8)) & 0xff;
+ _pBuffer[4 + i] = (low >> (i * 8)) & 0xff;
+ }
+ }
+ break;
+
+ case CMD_ORIGIN:
+ {
+ INFO_LOG(SERIALINTERFACE, "PAD - Get Origin");
+ u8* pCalibration = reinterpret_cast(&m_Origin);
+ for (int i = 0; i < (int)sizeof(SOrigin); i++)
+ {
+ _pBuffer[i ^ 3] = *pCalibration++;
+ }
+ }
+ break;
+
+ // Recalibrate (FiRES: i am not 100 percent sure about this)
+ case CMD_RECALIBRATE:
+ {
+ INFO_LOG(SERIALINTERFACE, "PAD - Recalibrate");
+ u8* pCalibration = reinterpret_cast(&m_Origin);
+ for (int i = 0; i < (int)sizeof(SOrigin); i++)
+ {
+ _pBuffer[i ^ 3] = *pCalibration++;
+ }
+ }
+ break;
+
+ // DEFAULT
+ default:
+ {
+ ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command);
+ PanicAlert("SI: Unknown command (0x%x)", command);
+ }
+ break;
+ }
+
+ return _iLength;
+}
+
+
+// GetData
+
+// Return true on new data (max 7 Bytes and 6 bits ;)
+// [00?SYXBA] [1LRZUDRL] [x] [y] [cx] [cy] [l] [r]
+// |\_ ERR_LATCH (error latched - check SISR)
+// |_ ERR_STATUS (error on last GetData or SendCmd?)
+bool CSIDevice_DanceMat::GetData(u32& _Hi, u32& _Low)
+{
+ SPADStatus PadStatus;
+ memset(&PadStatus, 0, sizeof(PadStatus));
+
+ Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
+ Movie::CallInputManip(&PadStatus, ISIDevice::m_iDeviceNumber);
+
+ u32 netValues[2];
+ if (NetPlay_GetInput(ISIDevice::m_iDeviceNumber, PadStatus, netValues))
+ {
+ _Hi = netValues[0]; // first 4 bytes
+ _Low = netValues[1]; // last 4 bytes
+ return true;
+ }
+
+ Movie::SetPolledDevice();
+
+ if(Movie::IsPlayingInput())
+ {
+ Movie::PlayController(&PadStatus, ISIDevice::m_iDeviceNumber);
+ Movie::InputUpdate();
+ }
+ else if(Movie::IsRecordingInput())
+ {
+ Movie::RecordInput(&PadStatus, ISIDevice::m_iDeviceNumber);
+ Movie::InputUpdate();
+ }
+ else
+ {
+ Movie::CheckPadStatus(&PadStatus, ISIDevice::m_iDeviceNumber);
+ }
+
+ // Map the dpad to the blue arrows, the buttons to the orange arrows
+ // Z = + button, Start = - button
+ u16 map = 0;
+ if (PadStatus.button & PAD_BUTTON_UP)
+ map |= 0x1000;
+ if (PadStatus.button & PAD_BUTTON_DOWN)
+ map |= 0x2;
+ if (PadStatus.button & PAD_BUTTON_LEFT)
+ map |= 0x8;
+ if (PadStatus.button & PAD_BUTTON_RIGHT)
+ map |= 0x4;
+ if (PadStatus.button & PAD_BUTTON_Y)
+ map |= 0x200;
+ if (PadStatus.button & PAD_BUTTON_A)
+ map |= 0x10;
+ if (PadStatus.button & PAD_BUTTON_B)
+ map |= 0x100;
+ if (PadStatus.button & PAD_BUTTON_X)
+ map |= 0x800;
+ if (PadStatus.button & PAD_TRIGGER_Z)
+ map |= 0x400;
+ if (PadStatus.button & PAD_BUTTON_START)
+ map |= 0x1;
+
+ _Hi = (u32)(map << 16) | 0x8080;
+
+ // Low bits are packed differently per mode
+ if (m_Mode == 0 || m_Mode == 5 || m_Mode == 6 || m_Mode == 7)
+ {
+ _Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
+ _Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
+ _Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 8); // Top 4 bits
+ _Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 12); // Top 4 bits
+ _Low |= (u32)((u8)(PadStatus.substickY) << 16); // All 8 bits
+ _Low |= (u32)((u8)(PadStatus.substickX) << 24); // All 8 bits
+ }
+ else if (m_Mode == 1)
+ {
+ _Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
+ _Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
+ _Low |= (u32)((u8)PadStatus.triggerRight << 8); // All 8 bits
+ _Low |= (u32)((u8)PadStatus.triggerLeft << 16); // All 8 bits
+ _Low |= (u32)((u8)PadStatus.substickY << 24); // Top 4 bits
+ _Low |= (u32)((u8)PadStatus.substickX << 28); // Top 4 bits
+ }
+ else if (m_Mode == 2)
+ {
+ // Identifies the dance mat
+ _Low = 0x8080ffff;
+ }
+ else if (m_Mode == 3)
+ {
+ // Analog A/B are always 0
+ _Low = (u8)PadStatus.triggerRight; // All 8 bits
+ _Low |= (u32)((u8)PadStatus.triggerLeft << 8); // All 8 bits
+ _Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
+ _Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
+ }
+ else if (m_Mode == 4)
+ {
+ _Low = (u8)(PadStatus.analogB); // All 8 bits
+ _Low |= (u32)((u8)(PadStatus.analogA) << 8); // All 8 bits
+ // triggerLeft/Right are always 0
+ _Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
+ _Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
+ }
+ return true;
+}
+
+
+// SendCommand
+void CSIDevice_DanceMat::SendCommand(u32 _Cmd, u8 _Poll)
+{
+ UCommand command(_Cmd);
+
+ switch (command.Command)
+ {
+ // Costis sent it in some demos :)
+ case 0x00:
+ break;
+
+ case CMD_WRITE:
+ {
+ unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
+ unsigned int uStrength = command.Parameter2;
+
+ // get the correct pad number that should rumble locally when using netplay
+ const u8 numPAD = NetPlay_GetPadNum(ISIDevice::m_iDeviceNumber);
+
+ if (numPAD < 4)
+ Pad::Rumble(numPAD, uType, uStrength);
+
+ if (!_Poll)
+ {
+ m_Mode = command.Parameter2;
+ INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode);
+ }
+ }
+ break;
+
+ default:
+ {
+ ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd);
+ PanicAlert("SI: Unknown direct command");
+ }
+ break;
+ }
+}
+
+// Savestate support
+void CSIDevice_DanceMat::DoState(PointerWrap& p)
+{
+ p.Do(m_Origin);
+ p.Do(m_Mode);
+ p.Do(m_TButtonComboStart);
+ p.Do(m_TButtonCombo);
+ p.Do(m_LastButtonCombo);
+}
diff --git a/Source/Core/Core/Src/HW/SI_DeviceDanceMat.h b/Source/Core/Core/Src/HW/SI_DeviceDanceMat.h
new file mode 100644
index 0000000000..b30c107847
--- /dev/null
+++ b/Source/Core/Core/Src/HW/SI_DeviceDanceMat.h
@@ -0,0 +1,105 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#ifndef _SI_DEVICEDANCEMAT_H
+#define _SI_DEVICEDANCEMAT_H
+
+#include "SI_Device.h"
+#include "GCPadStatus.h"
+
+
+// standard gamecube controller
+class CSIDevice_DanceMat : public ISIDevice
+{
+private:
+
+ // Commands
+ enum EBufferCommands
+ {
+ CMD_RESET = 0x00,
+ CMD_DIRECT = 0x40,
+ CMD_ORIGIN = 0x41,
+ CMD_RECALIBRATE = 0x42,
+ };
+
+ struct SOrigin
+ {
+ u8 uCommand;// Maybe should be button bits?
+ u8 unk_1; // ..and this would be the other half
+ u8 uOriginStickX;
+ u8 uOriginStickY;
+ u8 uSubStickStickX;
+ u8 uSubStickStickY;
+ u8 uTrigger_L;
+ u8 uTrigger_R;
+ u8 unk_4;
+ u8 unk_5;
+ u8 unk_6;
+ u8 unk_7;
+ };
+
+ enum EDirectCommands
+ {
+ CMD_WRITE = 0x40
+ };
+
+ union UCommand
+ {
+ u32 Hex;
+ struct
+ {
+ u32 Parameter1 : 8;
+ u32 Parameter2 : 8;
+ u32 Command : 8;
+ u32 : 8;
+ };
+ UCommand() {Hex = 0;}
+ UCommand(u32 _iValue) {Hex = _iValue;}
+ };
+
+ enum EButtonCombo
+ {
+ COMBO_NONE = 0,
+ COMBO_ORIGIN,
+ COMBO_RESET
+ };
+
+ // struct to compare input against
+ // Set on connection and (standard pad only) on button combo
+ SOrigin m_Origin;
+
+ // PADAnalogMode
+ u8 m_Mode;
+
+ // Timer to track special button combos:
+ // y, X, start for 3 seconds updates origin with current status
+ // Technically, the above is only on standard pad, wavebird does not support it for example
+ // b, x, start for 3 seconds triggers reset (PI reset button interrupt)
+ u64 m_TButtonComboStart, m_TButtonCombo;
+ // Type of button combo from the last/current poll
+ EButtonCombo m_LastButtonCombo;
+
+public:
+
+ // Constructor
+ CSIDevice_DanceMat(SIDevices device, int _iDeviceNumber);
+
+ // Run the SI Buffer
+ virtual int RunBuffer(u8* _pBuffer, int _iLength);
+
+ // Send and Receive pad input from network
+ static bool NetPlay_GetInput(u8 numPAD, SPADStatus status, u32 *PADStatus);
+ static u8 NetPlay_GetPadNum(u8 numPAD);
+
+ // Return true on new data
+ virtual bool GetData(u32& _Hi, u32& _Low);
+
+ // Send a command directly
+ virtual void SendCommand(u32 _Cmd, u8 _Poll);
+
+ // Savestate support
+ virtual void DoState(PointerWrap& p);
+};
+
+#endif
diff --git a/Source/Core/Core/Src/HW/VideoInterface.cpp b/Source/Core/Core/Src/HW/VideoInterface.cpp
index 5e7299586c..e5d32a9a8f 100644
--- a/Source/Core/Core/Src/HW/VideoInterface.cpp
+++ b/Source/Core/Core/Src/HW/VideoInterface.cpp
@@ -804,11 +804,9 @@ static void BeginField(FieldType field)
u32 fbWidth = m_HorizontalStepping.FieldSteps * 16;
u32 fbHeight = (m_HorizontalStepping.FbSteps / m_HorizontalStepping.FieldSteps) * m_VerticalTimingRegister.ACV;
- // TODO: Are the "Bottom Field" and "Top Field" registers actually more
- // like "First Field" and "Second Field" registers? There's an important
- // difference because NTSC and PAL have opposite field orders.
-
- u32 xfbAddr = (field == FIELD_LOWER) ? GetXFBAddressBottom() : GetXFBAddressTop();
+ // NTSC and PAL have opposite field orders.
+ FieldType order = (m_DisplayControlRegister.FMT == 0) ? FIELD_LOWER : FIELD_UPPER;
+ u32 xfbAddr = (field == order) ? GetXFBAddressBottom() : GetXFBAddressTop();
static const char* const fieldTypeNames[] = { "Progressive", "Upper", "Lower" };
diff --git a/Source/Core/Core/Src/HW/Wiimote.cpp b/Source/Core/Core/Src/HW/Wiimote.cpp
index 20e10b5fb8..6723a26d28 100644
--- a/Source/Core/Core/Src/HW/Wiimote.cpp
+++ b/Source/Core/Core/Src/HW/Wiimote.cpp
@@ -42,9 +42,10 @@ void Shutdown()
void Initialize(void* const hwnd)
{
// add 4 wiimotes
- for (unsigned int i = 0; i<4; ++i)
+ for (unsigned int i = WIIMOTE_CHAN_0; iDoState(p);
}
diff --git a/Source/Core/Core/Src/HW/Wiimote.h b/Source/Core/Core/Src/HW/Wiimote.h
index fa4ec895bd..51ab018417 100644
--- a/Source/Core/Core/Src/HW/Wiimote.h
+++ b/Source/Core/Core/Src/HW/Wiimote.h
@@ -8,7 +8,16 @@
#include "../../InputCommon/Src/InputConfig.h"
#include "ChunkFile.h"
-#define MAX_WIIMOTES 4
+enum {
+ WIIMOTE_CHAN_0 = 0,
+ WIIMOTE_CHAN_1,
+ WIIMOTE_CHAN_2,
+ WIIMOTE_CHAN_3,
+ WIIMOTE_BALANCE_BOARD,
+ MAX_WIIMOTES = WIIMOTE_BALANCE_BOARD,
+ MAX_BBMOTES = 5,
+};
+
#define WIIMOTE_INI_NAME "WiimoteNew"
@@ -20,7 +29,7 @@ enum
WIIMOTE_SRC_HYBRID = 3, // emu + real
};
-extern unsigned int g_wiimote_sources[MAX_WIIMOTES];
+extern unsigned int g_wiimote_sources[MAX_BBMOTES];
namespace Wiimote
{
diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp
index 0abe0d4b9c..47cb95905e 100644
--- a/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp
@@ -72,6 +72,7 @@ void Nunchuk::GetState(u8* const data, const bool focus)
m_stick->GetState(&ncdata->jx, &ncdata->jy, 0x80, focus ? 127 : 0);
AccelData accel;
+ accel_cal* calib = (accel_cal*)®[0x20];
// tilt
EmulateTilt(&accel, m_tilt, focus);
@@ -81,7 +82,7 @@ void Nunchuk::GetState(u8* const data, const bool focus)
// swing
EmulateSwing(&accel, m_swing);
// shake
- EmulateShake(&accel, m_shake, m_shake_step);
+ EmulateShake(&accel, calib, m_shake, m_shake_step);
// buttons
m_buttons->GetState(&ncdata->bt, nunchuk_button_bitmasks);
}
@@ -119,7 +120,6 @@ void Nunchuk::GetState(u8* const data, const bool focus)
}
wm_accel* dt = (wm_accel*)&ncdata->ax;
- accel_cal* calib = (accel_cal*)®[0x20];
dt->x = u8(trim(accel.x * (calib->one_g.x - calib->zero_g.x) + calib->zero_g.x));
dt->y = u8(trim(accel.y * (calib->one_g.y - calib->zero_g.y) + calib->zero_g.y));
dt->z = u8(trim(accel.z * (calib->one_g.z - calib->zero_g.z) + calib->zero_g.z));
diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp
index 196b38ab57..5ccfb19b43 100644
--- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp
@@ -86,6 +86,7 @@ const ReportFeatures reporting_mode_features[] =
};
void EmulateShake(AccelData* const accel
+ , accel_cal* const calib
, ControllerEmu::Buttons* const buttons_group
, u8* const shake_step )
{
@@ -94,7 +95,7 @@ void EmulateShake(AccelData* const accel
auto const shake_step_max = 15;
// peak G-force
- auto const shake_intensity = 3.f;
+ double shake_intensity;
// shake is a bitfield of X,Y,Z shake button states
static const unsigned int btns[] = { 0x01, 0x02, 0x04 };
@@ -105,6 +106,9 @@ void EmulateShake(AccelData* const accel
{
if (shake & (1 << i))
{
+ double zero = double((&(calib->zero_g.x))[i]);
+ double one = double((&(calib->one_g.x))[i]);
+ shake_intensity = max(zero / (one - zero), (255.f - zero) / (one - zero));
(&(accel->x))[i] = std::sin(TAU * shake_step[i] / shake_step_max) * shake_intensity;
shake_step[i] = (shake_step[i] + 1) % shake_step_max;
}
@@ -406,6 +410,7 @@ void Wiimote::GetAccelData(u8* const data, u8* const buttons)
const bool has_focus = HAS_FOCUS;
const bool is_sideways = m_options->settings[1]->value != 0;
const bool is_upright = m_options->settings[2]->value != 0;
+ accel_cal* calib = (accel_cal*)&m_eeprom[0x16];
// ----TILT----
EmulateTilt(&m_accel, m_tilt, has_focus, is_sideways, is_upright);
@@ -415,11 +420,10 @@ void Wiimote::GetAccelData(u8* const data, u8* const buttons)
if (has_focus)
{
EmulateSwing(&m_accel, m_swing, is_sideways, is_upright);
- EmulateShake(&m_accel, m_shake, m_shake_step);
+ EmulateShake(&m_accel, calib, m_shake, m_shake_step);
UDPTLayer::GetAcceleration(m_udp, &m_accel);
}
wm_accel* dt = (wm_accel*)data;
- accel_cal* calib = (accel_cal*)&m_eeprom[0x16];
double cx,cy,cz;
cx=trim(m_accel.x*(calib->one_g.x-calib->zero_g.x)+calib->zero_g.x);
cy=trim(m_accel.y*(calib->one_g.y-calib->zero_g.y)+calib->zero_g.y);
diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h
index 05045de32a..828594a4f7 100644
--- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h
+++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h
@@ -45,6 +45,7 @@ struct ADPCMState
extern const ReportFeatures reporting_mode_features[];
void EmulateShake(AccelData* const accel_data
+ , accel_cal* const calib
, ControllerEmu::Buttons* const buttons_group
, u8* const shake_step);
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
index 3a017354eb..59025f9040 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
@@ -32,9 +32,10 @@ WiimoteScanner::~WiimoteScanner()
void WiimoteScanner::Update()
{}
-std::vector WiimoteScanner::FindWiimotes()
+void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimote* & found_board)
{
- return std::vector();
+ found_wiimotes.clear();
+ found_board = NULL;
}
bool WiimoteScanner::IsReady() const
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
index 87ddc5086b..edd79f2bf6 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
@@ -63,23 +63,22 @@ WiimoteScanner::~WiimoteScanner()
void WiimoteScanner::Update()
{}
-std::vector WiimoteScanner::FindWiimotes()
+void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimote* & found_board)
{
- std::vector found_wiimotes;
-
// supposedly 1.28 seconds
int const wait_len = 1;
int const max_infos = 255;
inquiry_info scan_infos[max_infos] = {};
auto* scan_infos_ptr = scan_infos;
-
+ found_board = NULL;
+
// Scan for bluetooth devices
int const found_devices = hci_inquiry(device_id, wait_len, max_infos, NULL, &scan_infos_ptr, IREQ_CACHE_FLUSH);
if (found_devices < 0)
{
ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices.");
- return found_wiimotes;
+ return;
}
DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices);
@@ -91,7 +90,7 @@ std::vector WiimoteScanner::FindWiimotes()
// BT names are a maximum of 248 bytes apparently
char name[255] = {};
- if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 0) < 0)
+ if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 1000) < 0)
{
ERROR_LOG(WIIMOTE, "name request failed");
continue;
@@ -119,14 +118,20 @@ std::vector WiimoteScanner::FindWiimotes()
auto* const wm = new Wiimote;
wm->bdaddr = scan_infos[i].bdaddr;
- found_wiimotes.push_back(wm);
-
- NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str);
+ if(IsBalanceBoardName(name))
+ {
+ found_board = wm;
+ NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str);
+ }
+ else
+ {
+ found_wiimotes.push_back(wm);
+ NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str);
+ }
}
}
}
- return found_wiimotes;
}
// Connect to a wiimote with a known address.
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
index aa5b022a44..fc497c29a3 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
@@ -87,8 +87,8 @@ inline void init_lib()
hid_lib = LoadLibrary(_T("hid.dll"));
if (!hid_lib)
{
- PanicAlertT("Failed to load hid.dll");
- exit(EXIT_FAILURE);
+ PanicAlertT("Failed to load hid.dll! Connecting real Wiimotes won't work and Dolphin might crash unexpectedly!");
+ return;
}
HidD_GetHidGuid = (PHidD_GetHidGuid)GetProcAddress(hid_lib, "HidD_GetHidGuid");
@@ -98,15 +98,15 @@ inline void init_lib()
if (!HidD_GetHidGuid || !HidD_GetAttributes ||
!HidD_SetOutputReport || !HidD_GetProductString)
{
- PanicAlertT("Failed to load hid.dll");
- exit(EXIT_FAILURE);
+ PanicAlertT("Failed to load hid.dll! Connecting real Wiimotes won't work and Dolphin might crash unexpectedly!");
+ return;
}
bthprops_lib = LoadLibrary(_T("bthprops.cpl"));
if (!bthprops_lib)
{
- PanicAlertT("Failed to load bthprops.cpl");
- exit(EXIT_FAILURE);
+ PanicAlertT("Failed to load bthprops.cpl! Connecting real Wiimotes won't work and Dolphin might crash unexpectedly!");
+ return;
}
Bth_BluetoothFindDeviceClose = (PBth_BluetoothFindDeviceClose)GetProcAddress(bthprops_lib, "BluetoothFindDeviceClose");
@@ -128,8 +128,8 @@ inline void init_lib()
!Bth_BluetoothSetServiceState || !Bth_BluetoothAuthenticateDevice ||
!Bth_BluetoothEnumerateInstalledServices)
{
- PanicAlertT("Failed to load bthprops.cpl");
- exit(EXIT_FAILURE);
+ PanicAlertT("Failed to load bthprops.cpl! Connecting real Wiimotes won't work and Dolphin might crash unexpectedly!");
+ return;
}
initialized = true;
@@ -138,6 +138,10 @@ inline void init_lib()
namespace WiimoteReal
{
+
+
+int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len);
+int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index);
template
void ProcessWiimotes(bool new_scan, T& callback);
@@ -183,7 +187,7 @@ void WiimoteScanner::Update()
// Does not replace already found wiimotes even if they are disconnected.
// wm is an array of max_wiimotes wiimotes
// Returns the total number of found and connected wiimotes.
-std::vector WiimoteScanner::FindWiimotes()
+void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimote* & found_board)
{
ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
@@ -198,8 +202,6 @@ std::vector WiimoteScanner::FindWiimotes()
// Get all hid devices connected
HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
- std::vector wiimotes;
-
SP_DEVICE_INTERFACE_DATA device_data;
device_data.cbSize = sizeof(device_data);
PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
@@ -214,10 +216,24 @@ std::vector WiimoteScanner::FindWiimotes()
// Query the data for this device
if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL))
- {
+ {
auto const wm = new Wiimote;
wm->devicepath = detail_data->DevicePath;
- wiimotes.push_back(wm);
+ bool real_wiimote = false, is_bb = false;
+
+ CheckDeviceType(wm->devicepath, real_wiimote, is_bb);
+ if (is_bb)
+ {
+ found_board = wm;
+ }
+ else if (real_wiimote)
+ {
+ found_wiimotes.push_back(wm);
+ }
+ else
+ {
+ free(wm);
+ }
}
free(detail_data);
@@ -229,7 +245,183 @@ std::vector WiimoteScanner::FindWiimotes()
//if (!wiimotes.empty())
// SLEEP(2000);
- return wiimotes;
+}
+int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, int size, int attempts)
+{
+ OVERLAPPED hid_overlap_write = OVERLAPPED();
+ hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL);
+ enum win_bt_stack_t stack = MSBT_STACK_UNKNOWN;
+
+ DWORD written = 0;
+
+ for (; attempts>0; --attempts)
+ {
+ if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, size))
+ {
+ auto const wait_result = WaitForSingleObject(hid_overlap_write.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
+ if (WAIT_TIMEOUT == wait_result)
+ {
+ WARN_LOG(WIIMOTE, "CheckDeviceType_Write: A timeout occurred on writing to Wiimote.");
+ CancelIo(dev_handle);
+ continue;
+ }
+ else if (WAIT_FAILED == wait_result)
+ {
+ WARN_LOG(WIIMOTE, "CheckDeviceType_Write: A wait error occurred on writing to Wiimote.");
+ CancelIo(dev_handle);
+ continue;
+ }
+ if (GetOverlappedResult(dev_handle, &hid_overlap_write, &written, TRUE))
+ {
+ break;
+ }
+ }
+ }
+
+ CloseHandle(hid_overlap_write.hEvent);
+
+ return written;
+}
+
+int CheckDeviceType_Read(HANDLE &dev_handle, u8* buf, int attempts)
+{
+ OVERLAPPED hid_overlap_read = OVERLAPPED();
+ hid_overlap_read.hEvent = CreateEvent(NULL, true, false, NULL);
+ int read = 0;
+ for (; attempts>0; --attempts)
+ {
+ read = _IORead(dev_handle, hid_overlap_read, buf, 1);
+ if (read > 0)
+ break;
+ }
+
+ CloseHandle(hid_overlap_read.hEvent);
+
+ return read;
+}
+
+// A convoluted way of checking if a device is a Wii Balance Board and if it is a connectable Wiimote.
+// Because nothing on Windows should be easy.
+// (We can't seem to easily identify the bluetooth device an HID device belongs to...)
+void WiimoteScanner::CheckDeviceType(std::basic_string &devicepath, bool &real_wiimote, bool &is_bb)
+{
+ real_wiimote = false;
+ is_bb = false;
+
+#ifdef SHARE_WRITE_WIIMOTES
+ std::lock_guard lk(g_connected_wiimotes_lock);
+ if (g_connected_wiimotes.count(devicepath) != 0)
+ return;
+#endif
+
+ HANDLE dev_handle = CreateFile(devicepath.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
+ NULL);
+ if (dev_handle == INVALID_HANDLE_VALUE)
+ return;
+ // enable to only check for official nintendo wiimotes/bb's
+ bool check_vidpid = false;
+ HIDD_ATTRIBUTES attrib;
+ attrib.Size = sizeof(attrib);
+ if (!check_vidpid ||
+ (HidD_GetAttributes(dev_handle, &attrib) &&
+ (attrib.VendorID == 0x057e) &&
+ (attrib.ProductID == 0x0306)))
+ {
+ int rc = 0;
+ // max_cycles insures we are never stuck here due to bad coding...
+ int max_cycles = 20;
+ u8 buf[MAX_PAYLOAD] = {0};
+
+ u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0};
+
+ rc = CheckDeviceType_Write(dev_handle,
+ req_status_report,
+ sizeof(req_status_report),
+ 1);
+ while (rc > 0 && --max_cycles > 0)
+ {
+ if ((rc = CheckDeviceType_Read(dev_handle, buf, 1)) <= 0)
+ {
+ // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Read failed...");
+ break;
+ }
+
+ switch (buf[1])
+ {
+ case WM_STATUS_REPORT:
+ {
+ real_wiimote = true;
+
+ // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Status Report");
+ wm_status_report * wsr = (wm_status_report*)&buf[2];
+ if (wsr->extension)
+ {
+ // Wiimote with extension, we ask it what kind.
+ u8 read_ext[MAX_PAYLOAD] = {0};
+ read_ext[0] = WM_SET_REPORT | WM_BT_OUTPUT;
+ read_ext[1] = WM_READ_DATA;
+ // Extension type register.
+ *(u32*)&read_ext[2] = Common::swap32(0x4a400fa);
+ // Size.
+ *(u16*)&read_ext[6] = Common::swap16(6);
+ rc = CheckDeviceType_Write(dev_handle, read_ext, 8, 1);
+ }
+ else
+ {
+ // Normal Wiimote, exit while and be happy.
+ rc = -1;
+ }
+ break;
+ }
+ case WM_ACK_DATA:
+ {
+ real_wiimote = true;
+ //wm_acknowledge * wm = (wm_acknowledge*)&buf[2];
+ //DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Ack Error: %X ReportID: %X", wm->errorID, wm->reportID);
+ break;
+ }
+ case WM_READ_DATA_REPLY:
+ {
+ // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Data Reply");
+ wm_read_data_reply * wrdr
+ = (wm_read_data_reply*)&buf[2];
+ // Check if it has returned what we asked.
+ if (Common::swap16(wrdr->address) == 0x00fa)
+ {
+ real_wiimote = true;
+ // 0x020420A40000ULL means balance board.
+ u64 ext_type = (*(u64*)&wrdr->data[0]);
+ // DEBUG_LOG(WIIMOTE,
+ // "CheckDeviceType: GOT EXT TYPE %llX",
+ // ext_type);
+ is_bb = (ext_type == 0x020420A40000ULL) ||
+ ((ext_type & 0xf00000000000ULL) &&
+ ext_type != 0xffffffffffffULL);
+ }
+ else
+ {
+ ERROR_LOG(WIIMOTE,
+ "CheckDeviceType: GOT UNREQUESTED ADDRESS %X",
+ Common::swap16(wrdr->address));
+ }
+ // force end
+ rc = -1;
+
+ break;
+ }
+ default:
+ {
+ // We let read try again incase there is another packet waiting.
+ // DEBUG_LOG(WIIMOTE, "CheckDeviceType: GOT UNKNOWN REPLY: %X", buf[1]);
+ break;
+ }
+ }
+ }
+ }
+ CloseHandle(dev_handle);
}
bool WiimoteScanner::IsReady() const
@@ -355,7 +547,7 @@ bool Wiimote::IsConnected() const
// positive = read packet
// negative = didn't read packet
// zero = error
-int Wiimote::IORead(u8* buf)
+int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index)
{
// Add data report indicator byte (here, 0xa1)
buf[0] = 0xa1;
@@ -408,78 +600,92 @@ int Wiimote::IORead(u8* buf)
return bytes + 1;
}
-int Wiimote::IOWrite(const u8* buf, int len)
+// positive = read packet
+// negative = didn't read packet
+// zero = error
+int Wiimote::IORead(u8* buf)
+{
+ return _IORead(dev_handle, hid_overlap_read, buf, index);
+}
+
+
+int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len)
{
switch (stack)
{
- case MSBT_STACK_UNKNOWN:
- {
- // Try to auto-detect the stack type
- stack = MSBT_STACK_BLUESOLEIL;
- if (IOWrite(buf, len))
- return 1;
-
- stack = MSBT_STACK_MS;
- if (IOWrite(buf, len))
- return 1;
-
- stack = MSBT_STACK_UNKNOWN;
- break;
- }
- case MSBT_STACK_MS:
- {
- auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, len - 1);
- //FlushFileBuffers(dev_handle);
-
- if (!result)
+ case MSBT_STACK_UNKNOWN:
{
- auto err = GetLastError();
- if (err == 121)
+ // Try to auto-detect the stack type
+ stack = MSBT_STACK_BLUESOLEIL;
+ if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, len))
+ return 1;
+
+ stack = MSBT_STACK_MS;
+ if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, len))
+ return 1;
+
+ stack = MSBT_STACK_UNKNOWN;
+ break;
+ }
+ case MSBT_STACK_MS:
+ {
+ auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, len - 1);
+ //FlushFileBuffers(dev_handle);
+
+ if (!result)
{
- // Semaphore timeout
- NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to the Wiimote");
+ auto err = GetLastError();
+ if (err == 121)
+ {
+ // Semaphore timeout
+ NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to the Wiimote");
+ }
+ else
+ {
+ WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err);
+ }
+ }
+
+ return result;
+ break;
+ }
+ case MSBT_STACK_BLUESOLEIL:
+ {
+ u8 big_buf[MAX_PAYLOAD];
+ if (len < MAX_PAYLOAD)
+ {
+ std::copy(buf, buf + len, big_buf);
+ std::fill(big_buf + len, big_buf + MAX_PAYLOAD, 0);
+ buf = big_buf;
+ }
+
+ ResetEvent(hid_overlap_write.hEvent);
+ DWORD bytes = 0;
+ if (WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap_write))
+ {
+ // WriteFile always returns true with bluesoleil.
+ return 1;
}
else
{
- WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err);
+ auto const err = GetLastError();
+ if (ERROR_IO_PENDING == err)
+ {
+ CancelIo(dev_handle);
+ }
}
+ break;
}
-
- return result;
- break;
}
- case MSBT_STACK_BLUESOLEIL:
- {
- u8 big_buf[MAX_PAYLOAD];
- if (len < MAX_PAYLOAD)
- {
- std::copy(buf, buf + len, big_buf);
- std::fill(big_buf + len, big_buf + MAX_PAYLOAD, 0);
- buf = big_buf;
- }
-
- ResetEvent(hid_overlap_write.hEvent);
- DWORD bytes = 0;
- if (WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap_write))
- {
- // WriteFile always returns true with bluesoleil.
- return 1;
- }
- else
- {
- auto const err = GetLastError();
- if (ERROR_IO_PENDING == err)
- {
- CancelIo(dev_handle);
- }
- }
- break;
- }
- }
-
+
return 0;
}
+int Wiimote::IOWrite(const u8* buf, int len)
+{
+ return _IOWrite(dev_handle, hid_overlap_write, stack, buf, len);
+}
+
// invokes callback for each found wiimote bluetooth device
template
void ProcessWiimotes(bool new_scan, T& callback)
@@ -498,7 +704,7 @@ void ProcessWiimotes(bool new_scan, T& callback)
BLUETOOTH_FIND_RADIO_PARAMS radioParam;
radioParam.dwSize = sizeof(radioParam);
-
+
HANDLE hRadio;
// TODO: save radio(s) in the WiimoteScanner constructor?
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
index cec18ed63a..6f85f62a82 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
@@ -116,22 +116,21 @@ WiimoteScanner::~WiimoteScanner()
void WiimoteScanner::Update()
{}
-std::vector WiimoteScanner::FindWiimotes()
+void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimote* & found_board)
{
// TODO: find the device in the constructor and save it for later
-
- std::vector wiimotes;
IOBluetoothHostController *bth;
IOBluetoothDeviceInquiry *bti;
SearchBT *sbt;
NSEnumerator *en;
+ found_board = NULL;
bth = [[IOBluetoothHostController alloc] init];
if ([bth addressAsString] == nil)
{
WARN_LOG(WIIMOTE, "No bluetooth host controller");
[bth release];
- return wiimotes;
+ return;
}
sbt = [[SearchBT alloc] init];
@@ -162,14 +161,20 @@ std::vector WiimoteScanner::FindWiimotes()
Wiimote *wm = new Wiimote();
wm->btd = dev;
- wiimotes.push_back(wm);
+
+ if(IsBalanceBoardName([[dev name] UTF8String]))
+ {
+ found_board = wm;
+ }
+ else
+ {
+ found_wiimotes.push_back(wm);
+ }
}
[bth release];
[bti release];
[sbt release];
-
- return wiimotes;
}
bool WiimoteScanner::IsReady() const
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
index aaaaff6301..40c6ee0554 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
@@ -17,12 +17,13 @@
#include "../WiimoteEmu/WiimoteHid.h"
-unsigned int g_wiimote_sources[MAX_WIIMOTES];
+unsigned int g_wiimote_sources[MAX_BBMOTES];
namespace WiimoteReal
{
void HandleFoundWiimotes(const std::vector&);
+void TryToConnectBalanceBoard(Wiimote*);
void TryToConnectWiimote(Wiimote*);
void HandleWiimoteDisconnect(int index);
void DoneWithWiimote(int index);
@@ -31,8 +32,7 @@ bool g_real_wiimotes_initialized = false;
std::recursive_mutex g_refresh_lock;
-Wiimote* g_wiimotes[MAX_WIIMOTES];
-
+Wiimote* g_wiimotes[MAX_BBMOTES];
WiimoteScanner g_wiimote_scanner;
Wiimote::Wiimote()
@@ -285,7 +285,7 @@ bool Wiimote::Prepare(int _index)
u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE};
// Set the active LEDs and turn on rumble.
- u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << index | 0x1)};
+ u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << (index%WIIMOTE_BALANCE_BOARD) | 0x1)};
// Turn off rumble
u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0};
@@ -325,11 +325,25 @@ unsigned int CalculateWantedWiimotes()
return wanted_wiimotes;
}
+unsigned int CalculateWantedBB()
+{
+ unsigned int wanted_bb = 0;
+ if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD] && !g_wiimotes[WIIMOTE_BALANCE_BOARD])
+ ++wanted_bb;
+ return wanted_bb;
+}
+
void WiimoteScanner::WantWiimotes(bool do_want)
{
m_want_wiimotes = do_want;
}
+
+void WiimoteScanner::WantBB(bool do_want)
+{
+ m_want_bb = do_want;
+}
+
void WiimoteScanner::StartScanning()
{
if (!m_run_thread)
@@ -352,7 +366,7 @@ void CheckForDisconnectedWiimotes()
{
std::lock_guard lk(g_refresh_lock);
- for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
+ for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected())
HandleWiimoteDisconnect(i);
}
@@ -366,12 +380,13 @@ void WiimoteScanner::ThreadFunc()
while (m_run_thread)
{
std::vector found_wiimotes;
+ Wiimote* found_board = NULL;
//NOTICE_LOG(WIIMOTE, "In loop");
- if (m_want_wiimotes)
+ if (m_want_wiimotes || m_want_bb)
{
- found_wiimotes = FindWiimotes();
+ FindWiimotes(found_wiimotes, found_board);
}
else
{
@@ -384,7 +399,10 @@ void WiimoteScanner::ThreadFunc()
// TODO: this is a fairly lame place for this
CheckForDisconnectedWiimotes();
- HandleFoundWiimotes(found_wiimotes);
+ if(m_want_wiimotes)
+ HandleFoundWiimotes(found_wiimotes);
+ if(m_want_bb && found_board)
+ TryToConnectBalanceBoard(found_board);
//std::this_thread::yield();
Common::SleepCurrentThread(500);
@@ -439,6 +457,10 @@ void LoadSettings()
sec.Get("Source", &g_wiimote_sources[i], i ? WIIMOTE_SRC_NONE : WIIMOTE_SRC_EMU);
}
+
+ std::string secname("BalanceBoard");
+ IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str());
+ sec.Get("Source", &g_wiimote_sources[WIIMOTE_BALANCE_BOARD], WIIMOTE_SRC_NONE);
}
// config dialog calls this when some settings change
@@ -452,6 +474,7 @@ void Initialize()
std::lock_guard lk(g_refresh_lock);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
+ g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
if (g_real_wiimotes_initialized)
return;
@@ -474,20 +497,21 @@ void Shutdown(void)
g_real_wiimotes_initialized = false;
- for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
+ for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
HandleWiimoteDisconnect(i);
}
void ChangeWiimoteSource(unsigned int index, int source)
{
{
- std::lock_guard lk(g_refresh_lock);
-
- g_wiimote_sources[index] = source;
- g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
-
- // kill real connection (or swap to different slot)
- DoneWithWiimote(index);
+ std::lock_guard lk(g_refresh_lock);
+ g_wiimote_sources[index] = source;
+ g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
+ g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
+
+
+ // kill real connection (or swap to different slot)
+ DoneWithWiimote(index);
}
// reconnect to the emulator
@@ -500,7 +524,7 @@ void TryToConnectWiimote(Wiimote* wm)
{
std::unique_lock lk(g_refresh_lock);
- for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
+ for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
&& !g_wiimotes[i])
@@ -525,16 +549,41 @@ void TryToConnectWiimote(Wiimote* wm)
delete wm;
}
+void TryToConnectBalanceBoard(Wiimote* wm)
+{
+ std::unique_lock lk(g_refresh_lock);
+
+ if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD]
+ && !g_wiimotes[WIIMOTE_BALANCE_BOARD])
+ {
+ if (wm->Connect() && wm->Prepare(WIIMOTE_BALANCE_BOARD))
+ {
+ NOTICE_LOG(WIIMOTE, "Connected to Balance Board %i.", WIIMOTE_BALANCE_BOARD + 1);
+
+ std::swap(g_wiimotes[WIIMOTE_BALANCE_BOARD], wm);
+ g_wiimotes[WIIMOTE_BALANCE_BOARD]->StartThread();
+
+ Host_ConnectWiimote(WIIMOTE_BALANCE_BOARD, true);
+ }
+ }
+
+ g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
+
+ lk.unlock();
+
+ delete wm;
+}
+
void DoneWithWiimote(int index)
{
std::lock_guard lk(g_refresh_lock);
-
+
if (g_wiimotes[index])
{
g_wiimotes[index]->StopThread();
// First see if we can use this real Wiimote in another slot.
- for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
+ for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
&& !g_wiimotes[i])
@@ -560,9 +609,11 @@ void HandleWiimoteDisconnect(int index)
Wiimote* wm = NULL;
{
- std::lock_guard lk(g_refresh_lock);
- std::swap(wm, g_wiimotes[index]);
- g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
+ std::lock_guard lk(g_refresh_lock);
+
+ std::swap(wm, g_wiimotes[index]);
+ g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
+ g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
}
if (wm)
@@ -583,31 +634,35 @@ void Refresh()
g_wiimote_scanner.StopScanning();
{
- std::unique_lock lk(g_refresh_lock);
- std::vector found_wiimotes;
-
- if (0 != CalculateWantedWiimotes())
- {
- // Don't hang Dolphin when searching
- lk.unlock();
- found_wiimotes = g_wiimote_scanner.FindWiimotes();
- lk.lock();
- }
-
- CheckForDisconnectedWiimotes();
-
- // Brief rumble for already connected Wiimotes.
- for (int i = 0; i != MAX_WIIMOTES; ++i)
- {
- if (g_wiimotes[i])
+ std::unique_lock lk(g_refresh_lock);
+ std::vector found_wiimotes;
+ Wiimote* found_board = NULL;
+
+ if (0 != CalculateWantedWiimotes() || 0 != CalculateWantedBB())
{
- g_wiimotes[i]->StopThread();
- g_wiimotes[i]->Prepare(i);
- g_wiimotes[i]->StartThread();
+ // Don't hang Dolphin when searching
+ lk.unlock();
+ g_wiimote_scanner.FindWiimotes(found_wiimotes, found_board);
+ lk.lock();
}
- }
- HandleFoundWiimotes(found_wiimotes);
+ CheckForDisconnectedWiimotes();
+
+ // Brief rumble for already connected Wiimotes.
+ // Don't do this for Balance Board as it doesn't have rumble anyway.
+ for (int i = 0; i < MAX_WIIMOTES; ++i)
+ {
+ if (g_wiimotes[i])
+ {
+ g_wiimotes[i]->StopThread();
+ g_wiimotes[i]->Prepare(i);
+ g_wiimotes[i]->StartThread();
+ }
+ }
+
+ HandleFoundWiimotes(found_wiimotes);
+ if(found_board)
+ TryToConnectBalanceBoard(found_board);
}
Initialize();
@@ -616,7 +671,6 @@ void Refresh()
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{
std::lock_guard lk(g_refresh_lock);
-
if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size);
}
@@ -656,7 +710,14 @@ bool IsValidBluetoothName(const std::string& name)
{
return
"Nintendo RVL-CNT-01" == name ||
- "Nintendo RVL-CNT-01-TR" == name;
+ "Nintendo RVL-CNT-01-TR" == name ||
+ IsBalanceBoardName(name);
+}
+
+bool IsBalanceBoardName(const std::string& name)
+{
+ return
+ "Nintendo RVL-WBC-01" == name;
}
}; // end of namespace
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
index b57e1be2f4..d195f92120 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
@@ -117,11 +117,12 @@ public:
bool IsReady() const;
void WantWiimotes(bool do_want);
+ void WantBB(bool do_want);
void StartScanning();
void StopScanning();
- std::vector FindWiimotes();
+ void FindWiimotes(std::vector&, Wiimote*&);
// function called when not looking for more wiimotes
void Update();
@@ -133,10 +134,10 @@ private:
volatile bool m_run_thread;
volatile bool m_want_wiimotes;
+ volatile bool m_want_bb;
#if defined(_WIN32)
-
-
+ void CheckDeviceType(std::basic_string &devicepath, bool &real_wiimote, bool &is_bb);
#elif defined(__linux__) && HAVE_BLUEZ
int device_id;
int device_sock;
@@ -145,7 +146,7 @@ private:
extern std::recursive_mutex g_refresh_lock;
extern WiimoteScanner g_wiimote_scanner;
-extern Wiimote *g_wiimotes[4];
+extern Wiimote *g_wiimotes[MAX_BBMOTES];
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
@@ -158,6 +159,7 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes);
void ChangeWiimoteSource(unsigned int index, int source);
bool IsValidBluetoothName(const std::string& name);
+bool IsBalanceBoardName(const std::string& name);
}; // WiimoteReal
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
index 41f751cb77..daa28b340d 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
@@ -32,7 +32,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
}
else
{
- u8 maxWM = min(BT_DINF.num_registered, CONF_PAD_MAX_ACTIVE);
+ u8 maxWM = min(BT_DINF.num_registered, MAX_BBMOTES);
bdaddr_t tmpBD = BDADDR_ANY;
u8 i = 0;
while (i < maxWM)
@@ -43,28 +43,60 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
tmpBD.b[2] = BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3];
tmpBD.b[1] = BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4];
tmpBD.b[0] = BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5];
+ if(i == WIIMOTE_BALANCE_BOARD)
+ {
+ const char * wmName = "Nintendo RVL-WBC-01";
+ memcpy(BT_DINF.registered[i].name, wmName, 20);
+ memcpy(BT_DINF.balance_board.name, wmName, 20);
+ }
+ else
+ {
+ const char * wmName = "Nintendo RVL-CNT-01";
+ memcpy(BT_DINF.registered[i].name, wmName, 20);
+ memcpy(BT_DINF.active[i].name, wmName, 20);
+ }
INFO_LOG(WII_IPC_WIIMOTE, "Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
i++;
}
- while (i < CONF_PAD_MAX_ACTIVE)
+ while (i < MAX_BBMOTES)
{
- const char * wmName = "Nintendo RVL-CNT-01";
- ++BT_DINF.num_registered;
- BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
- BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
- BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
- BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
- BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
- BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
- memcpy(BT_DINF.registered[i].name, wmName, 20);
+ if(i == WIIMOTE_BALANCE_BOARD)
+ {
+ const char * wmName = "Nintendo RVL-WBC-01";
+ ++BT_DINF.num_registered;
+ BT_DINF.balance_board.bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
+ BT_DINF.balance_board.bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
+ BT_DINF.balance_board.bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
+ BT_DINF.balance_board.bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
+ BT_DINF.balance_board.bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
+ BT_DINF.balance_board.bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
+ memcpy(BT_DINF.registered[i].name, wmName, 20);
+ memcpy(BT_DINF.balance_board.name, wmName, 20);
+
+ INFO_LOG(WII_IPC_WIIMOTE, "Balance Board %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
+ m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
+ }
+ else
+ {
+ const char * wmName = "Nintendo RVL-CNT-01";
+ ++BT_DINF.num_registered;
+ BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
+ BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
+ BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
+ BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
+ BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
+ BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
+ memcpy(BT_DINF.registered[i].name, wmName, 20);
- INFO_LOG(WII_IPC_WIIMOTE, "Adding to SYSConf Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
- m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
+ INFO_LOG(WII_IPC_WIIMOTE, "Adding to SYSConf Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
+ m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
+
+ }
i++;
}
-
+
// save now so that when games load sysconf file it includes the new wiimotes
// and the correct order for connected wiimotes
if (!SConfig::GetInstance().m_SYSCONF->SetArrayData("BT.DINF", (u8*)&BT_DINF, sizeof(_conf_pads)) || !SConfig::GetInstance().m_SYSCONF->Save())
@@ -99,18 +131,18 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p)
p.DoPOD(m_HCIEndpoint);
p.DoPOD(m_ACLEndpoint);
p.Do(m_last_ticks);
- p.DoArray(m_PacketCount,4);
+ p.DoArray(m_PacketCount,MAX_BBMOTES);
p.Do(m_ScanEnable);
p.Do(m_EventQueue);
m_acl_pool.DoState(p);
- for (unsigned int i = 0; i < 4; i++)
+ for (unsigned int i = 0; i < MAX_BBMOTES; i++)
m_WiiMotes[i].DoState(p);
// Reset the connection of real and hybrid wiimotes
if (p.GetMode() == PointerWrap::MODE_READ && SConfig::GetInstance().m_WiimoteReconnectOnLoad)
{
- for (unsigned int i = 0; i < 4; i++)
+ for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
if (WIIMOTE_SRC_EMU == g_wiimote_sources[i] || WIIMOTE_SRC_NONE == g_wiimote_sources[i])
continue;
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
index f3d79b0fb8..7ac93b5be1 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
@@ -12,6 +12,7 @@
#include "WII_IPC_HLE.h"
#include "WII_IPC_HLE_Device.h"
#include "WII_IPC_HLE_WiiMote.h"
+#include "../HW/Wiimote.h"
struct SQueuedEvent
{
@@ -193,7 +194,7 @@ private:
}
} m_acl_pool;
- u32 m_PacketCount[4];
+ u32 m_PacketCount[MAX_BBMOTES];
u64 m_last_ticks;
// Send ACL data to a device (wiimote)
@@ -274,7 +275,6 @@ private:
#pragma pack(push,1)
#define CONF_PAD_MAX_REGISTERED 10
-#define CONF_PAD_MAX_ACTIVE 4
struct _conf_pad_device
{
@@ -286,7 +286,7 @@ private:
{
u8 num_registered;
_conf_pad_device registered[CONF_PAD_MAX_REGISTERED];
- _conf_pad_device active[CONF_PAD_MAX_ACTIVE];
+ _conf_pad_device active[MAX_WIIMOTES];
_conf_pad_device balance_board;
u8 unknown[0x45];
};
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
index 22930eb94c..9386682106 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
@@ -37,7 +37,7 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
, m_HIDInterruptChannel_Config(false)
, m_HIDInterruptChannel_ConfigWait(false)
, m_BD(_BD)
- , m_Name("Nintendo RVL-CNT-01")
+ , m_Name(_Number == WIIMOTE_BALANCE_BOARD ? "Nintendo RVL-WBC-01" : "Nintendo RVL-CNT-01")
, m_pHost(_pHost)
{
DEBUG_LOG(WII_IPC_WIIMOTE, "Wiimote: #%i Constructed", _Number);
@@ -277,13 +277,13 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size)
break;
case L2CAP_PSM_HID_CNTL:
- if (number < 4)
+ if (number < MAX_BBMOTES)
Wiimote::ControlChannel(number, pHeader->dcid, pData, DataSize);
break;
case L2CAP_PSM_HID_INTR:
{
- if (number < 4)
+ if (number < MAX_BBMOTES)
{
DEBUG_LOG(WIIMOTE, "Wiimote_InterruptChannel");
DEBUG_LOG(WIIMOTE, " Channel ID: %04x", pHeader->dcid);
diff --git a/Source/Core/Core/Src/Movie.cpp b/Source/Core/Core/Src/Movie.cpp
index c57ce8d4cc..5a81c7d904 100644
--- a/Source/Core/Core/Src/Movie.cpp
+++ b/Source/Core/Core/Src/Movie.cpp
@@ -126,11 +126,6 @@ void FrameUpdate()
g_totalFrames = g_currentFrame;
g_totalLagCount = g_currentLagCount;
}
- if (IsPlayingInput() && IsConfigSaved())
- {
- SetGraphicsConfig();
- }
-
if (g_bFrameStep)
{
Core::SetState(Core::CORE_PAUSE);
@@ -392,7 +387,7 @@ void ChangeWiiPads(bool instantly)
if (instantly && (g_numPads >> 4) == controllers)
return;
- for (int i = 0; i < 4; i++)
+ for (int i = 0; i < MAX_BBMOTES; i++)
{
g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE;
GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i));
@@ -1173,18 +1168,15 @@ void GetSettings()
bProgressive = SConfig::GetInstance().m_LocalCoreStartupParameter.bProgressive;
bDSPHLE = SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPHLE;
bFastDiscSpeed = SConfig::GetInstance().m_LocalCoreStartupParameter.bFastDiscSpeed;
- videoBackend = SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoBackend;
+ videoBackend = g_video_backend->GetName();
iCPUCore = SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore;
if (!Core::g_CoreStartupParameter.bWii)
g_bClearSave = !File::Exists(SConfig::GetInstance().m_strMemoryCardA);
bMemcard = SConfig::GetInstance().m_EXIDevice[0] == EXIDEVICE_MEMORYCARD;
- int temp;
-
- for(int i = 0; i < 4; ++i )
+ for (int i = 0; i < 20; ++i)
{
- sscanf(SCM_REV_STR + 2 * i, "%2x", &temp );
- revision[i] = temp;
+ sscanf(SCM_REV_STR + 2 * i, "%02x", &revision[i]);
}
}
diff --git a/Source/Core/Core/Src/NetPlay.cpp b/Source/Core/Core/Src/NetPlay.cpp
index 96c4a69f98..7f4b838ffc 100644
--- a/Source/Core/Core/Src/NetPlay.cpp
+++ b/Source/Core/Core/Src/NetPlay.cpp
@@ -10,6 +10,7 @@
// for gcpad
#include "HW/SI_DeviceGCController.h"
#include "HW/SI_DeviceGCSteeringWheel.h"
+#include "HW/SI_DeviceDanceMat.h"
// for gctime
#include "HW/EXI_DeviceIPL.h"
// for wiimote/ OSD messages
@@ -299,6 +300,11 @@ bool CSIDevice_GCSteeringWheel::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus
return CSIDevice_GCController::NetPlay_GetInput(numPAD, PadStatus, PADStatus);
}
+bool CSIDevice_DanceMat::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
+{
+ return CSIDevice_GCController::NetPlay_GetInput(numPAD, PadStatus, PADStatus);
+}
+
// called from ---CPU--- thread
// so all players' games get the same time
u32 CEXIIPL::NetPlay_GetGCTime()
@@ -328,6 +334,11 @@ u8 CSIDevice_GCSteeringWheel::NetPlay_GetPadNum(u8 numPAD)
return CSIDevice_GCController::NetPlay_GetPadNum(numPAD);
}
+u8 CSIDevice_DanceMat::NetPlay_GetPadNum(u8 numPAD)
+{
+ return CSIDevice_GCController::NetPlay_GetPadNum(numPAD);
+}
+
// called from ---CPU--- thread
// wiimote update / used for frame counting
//void CWII_IPC_HLE_Device_usb_oh1_57e_305::NetPlay_WiimoteUpdate(int _number)
diff --git a/Source/Core/Core/Src/PowerPC/PPCCache.cpp b/Source/Core/Core/Src/PowerPC/PPCCache.cpp
index 4ead232b18..e1940ec18c 100644
--- a/Source/Core/Core/Src/PowerPC/PPCCache.cpp
+++ b/Source/Core/Core/Src/PowerPC/PPCCache.cpp
@@ -26,31 +26,29 @@ namespace PowerPC
for (u32 m = 0; m < 128; m++)
{
- u32 b[7];
- for (int i = 0; i < 7; i++) b[i] = m & (1<& buffer)
Core::PauseAndLock(false, wasUnpaused);
}
+// return state number not in map
+int GetEmptySlot(std::map m)
+{
+ for (int i = 1; i <= (int)NUM_STATES; i++)
+ {
+ bool found = false;
+ for (std::map::iterator it = m.begin(); it != m.end(); it++)
+ {
+ if (it->second == i)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found) return i;
+ }
+ return -1;
+}
+
+static std::string MakeStateFilename(int number);
+
+// read state timestamps
+std::map GetSavedStates()
+{
+ StateHeader header;
+ std::map m;
+ for (int i = 1; i <= (int)NUM_STATES; i++)
+ {
+ if (File::Exists(MakeStateFilename(i)))
+ {
+ if (ReadHeader(MakeStateFilename(i), header))
+ {
+ double d = Common::Timer::GetDoubleTime() - header.time;
+ // increase time until unique value is obtained
+ while (m.find(d) != m.end()) d += .001;
+ m.insert(std::pair(d, i));
+ }
+ }
+ }
+ return m;
+}
+
struct CompressAndDumpState_args
{
std::vector* buffer_vector;
std::mutex* buffer_mutex;
std::string filename;
+ bool wait;
};
void CompressAndDumpState(CompressAndDumpState_args save_args)
{
std::lock_guard lk(*save_args.buffer_mutex);
- g_compressAndDumpStateSyncEvent.Set();
+ if (!save_args.wait)
+ g_compressAndDumpStateSyncEvent.Set();
const u8* const buffer_data = &(*(save_args.buffer_vector))[0];
const size_t buffer_size = (save_args.buffer_vector)->size();
@@ -201,6 +240,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args)
if (!f)
{
Core::DisplayMessage("Could not save state", 2000);
+ g_compressAndDumpStateSyncEvent.Set();
return;
}
@@ -208,6 +248,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args)
StateHeader header;
memcpy(header.gameID, SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), 6);
header.size = g_use_compression ? buffer_size : 0;
+ header.time = Common::Timer::GetDoubleTime();
f.WriteArray(&header, 1);
@@ -216,7 +257,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args)
lzo_uint i = 0;
while (true)
{
- lzo_uint cur_len = 0;
+ lzo_uint32 cur_len = 0;
lzo_uint out_len = 0;
if ((i + IN_LEN) >= buffer_size)
@@ -228,7 +269,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args)
PanicAlertT("Internal LZO Error - compression failed");
// The size of the data to write is 'out_len'
- f.WriteArray(&out_len, 1);
+ f.WriteArray((lzo_uint32*)&out_len, 1);
f.WriteBytes(out, out_len);
if (cur_len != IN_LEN)
@@ -244,9 +285,10 @@ void CompressAndDumpState(CompressAndDumpState_args save_args)
Core::DisplayMessage(StringFromFormat("Saved State to %s",
filename.c_str()).c_str(), 2000);
+ g_compressAndDumpStateSyncEvent.Set();
}
-void SaveAs(const std::string& filename)
+void SaveAs(const std::string& filename, bool wait)
{
// Pause the core while we save the state
bool wasUnpaused = Core::PauseAndLock(true);
@@ -274,6 +316,7 @@ void SaveAs(const std::string& filename)
save_args.buffer_vector = &g_current_buffer;
save_args.buffer_mutex = &g_cs_current_buffer;
save_args.filename = filename;
+ save_args.wait = wait;
Flush();
g_save_thread = std::thread(CompressAndDumpState, save_args);
@@ -291,6 +334,20 @@ void SaveAs(const std::string& filename)
Core::PauseAndLock(false, wasUnpaused);
}
+bool ReadHeader(const std::string filename, StateHeader& header)
+{
+ Flush();
+ File::IOFile f(filename, "rb");
+ if (!f)
+ {
+ Core::DisplayMessage("State not found", 2000);
+ return false;
+ }
+
+ f.ReadArray(&header, 1);
+ return true;
+}
+
void LoadFileStateData(const std::string& filename, std::vector& ret_data)
{
Flush();
@@ -322,7 +379,7 @@ void LoadFileStateData(const std::string& filename, std::vector& ret_data)
lzo_uint i = 0;
while (true)
{
- lzo_uint cur_len = 0; // number of bytes to read
+ lzo_uint32 cur_len = 0; // number of bytes to read
lzo_uint new_len = 0; // number of bytes to write
if (!f.ReadArray(&cur_len, 1))
@@ -496,9 +553,9 @@ static std::string MakeStateFilename(int number)
SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), number);
}
-void Save(int slot)
+void Save(int slot, bool wait)
{
- SaveAs(MakeStateFilename(slot));
+ SaveAs(MakeStateFilename(slot), wait);
}
void Load(int slot)
@@ -511,12 +568,35 @@ void Verify(int slot)
VerifyAt(MakeStateFilename(slot));
}
-void LoadLastSaved()
+void LoadLastSaved(int i)
{
- if (g_last_filename.empty())
- Core::DisplayMessage("There is no last saved state", 2000);
+ std::map savedStates = GetSavedStates();
+
+ if (i > (int)savedStates.size())
+ Core::DisplayMessage("State doesn't exist", 2000);
else
- LoadAs(g_last_filename);
+ {
+ std::map::iterator it = savedStates.begin();
+ std::advance(it, i-1);
+ Load(it->second);
+ }
+}
+
+// must wait for state to be written because it must know if all slots are taken
+void SaveFirstSaved()
+{
+ std::map savedStates = GetSavedStates();
+
+ // save to an empty slot
+ if (savedStates.size() < NUM_STATES)
+ Save(GetEmptySlot(savedStates), true);
+ // overwrite the oldest state
+ else
+ {
+ std::map::iterator it = savedStates.begin();
+ std::advance(it, savedStates.size()-1);
+ Save(it->second, true);
+ }
}
void Flush()
diff --git a/Source/Core/Core/Src/State.h b/Source/Core/Core/Src/State.h
index db88cef766..302e25d617 100644
--- a/Source/Core/Core/Src/State.h
+++ b/Source/Core/Core/Src/State.h
@@ -14,22 +14,34 @@
namespace State
{
+// number of states
+static const u32 NUM_STATES = 8;
+
+struct StateHeader
+{
+ u8 gameID[6];
+ u32 size;
+ double time;
+};
+
void Init();
void Shutdown();
void EnableCompression(bool compression);
+bool ReadHeader(const std::string filename, StateHeader& header);
+
// These don't happen instantly - they get scheduled as events.
// ...But only if we're not in the main cpu thread.
// If we're in the main cpu thread then they run immediately instead
// because some things (like Lua) need them to run immediately.
// Slots from 0-99.
-void Save(int slot);
+void Save(int slot, bool wait = false);
void Load(int slot);
void Verify(int slot);
-void SaveAs(const std::string &filename);
+void SaveAs(const std::string &filename, bool wait = false);
void LoadAs(const std::string &filename);
void VerifyAt(const std::string &filename);
@@ -37,7 +49,8 @@ void SaveToBuffer(std::vector& buffer);
void LoadFromBuffer(std::vector& buffer);
void VerifyBuffer(std::vector& buffer);
-void LoadLastSaved();
+void LoadLastSaved(int i = 1);
+void SaveFirstSaved();
void UndoSaveState();
void UndoLoadState();
diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt
index 9508f75a36..e3f8789634 100644
--- a/Source/Core/DolphinWX/CMakeLists.txt
+++ b/Source/Core/DolphinWX/CMakeLists.txt
@@ -172,6 +172,9 @@ if(ANDROID)
${LIBS}
"-Wl,--no-whole-archive"
)
+ add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD
+ COMMAND cp ARGS ${CMAKE_SOURCE_DIR}/libs/armeabi-v7a/lib${DOLPHIN_EXE}.so ${CMAKE_SOURCE_DIR}/Source/Android/libs/armeabi-v7a
+ )
else()
add_executable(${DOLPHIN_EXE} ${SRCS})
target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS})
diff --git a/Source/Core/DolphinWX/Src/CheatsWindow.cpp b/Source/Core/DolphinWX/Src/CheatsWindow.cpp
index e3a51208b4..7d92d7cb04 100644
--- a/Source/Core/DolphinWX/Src/CheatsWindow.cpp
+++ b/Source/Core/DolphinWX/Src/CheatsWindow.cpp
@@ -14,6 +14,7 @@
#include "WxUtils.h"
#define MAX_CHEAT_SEARCH_RESULTS_DISPLAY 256
+const wxString title = _("Cheats Manager");
extern std::vector arCodes;
extern CFrame* main_frame;
@@ -22,26 +23,15 @@ extern CFrame* main_frame;
static wxCheatsWindow *g_cheat_window;
wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
- : wxDialog(parent, wxID_ANY, _("Cheats Manager"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxDIALOG_NO_PARENT)
+ : wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxDIALOG_NO_PARENT)
{
::g_cheat_window = this;
// Create the GUI controls
Init_ChildControls();
- // Load Data
- Load_ARCodes();
-
- // Load Gecko Codes :/
- {
- const DiscIO::IVolume* const vol = VolumeHandler::GetVolume();
- if (vol)
- {
- m_gameini_path = File::GetUserPath(D_GAMECONFIG_IDX) + vol->GetUniqueID() + ".ini";
- m_gameini.Load(m_gameini_path);
- m_geckocode_panel->LoadCodes(m_gameini);
- }
- }
+ // load codes
+ UpdateGUI();
SetSize(wxSize(-1, 600));
Center();
@@ -119,7 +109,7 @@ void wxCheatsWindow::Init_ChildControls()
m_Notebook_Main->AddPage(m_Tab_Log, _("Logging"));
// Button Strip
- wxButton* const button_apply = new wxButton(panel, wxID_APPLY, _("Apply"), wxDefaultPosition, wxDefaultSize);
+ button_apply = new wxButton(panel, wxID_APPLY, _("Apply"), wxDefaultPosition, wxDefaultSize);
button_apply->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &wxCheatsWindow::OnEvent_ApplyChanges_Press, this);
wxButton* const button_cancel = new wxButton(panel, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize);
button_cancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &wxCheatsWindow::OnEvent_ButtonClose_Press, this);
@@ -249,12 +239,34 @@ void wxCheatsWindow::OnEvent_Close(wxCloseEvent& ev)
Destroy();
}
+// load codes for a new ISO ID
+void wxCheatsWindow::UpdateGUI()
+{
+ // load code
+ m_gameini_path = File::GetUserPath(D_GAMECONFIG_IDX) + Core::g_CoreStartupParameter.GetUniqueID() + ".ini";
+ m_gameini.Load(m_gameini_path);
+ Load_ARCodes();
+ Load_GeckoCodes();
+
+ // enable controls
+ button_apply->Enable(Core::IsRunning());
+
+ // write the ISO name in the title
+ if (Core::IsRunning())
+ SetTitle(title + ": " + Core::g_CoreStartupParameter.GetUniqueID() + " - " + Core::g_CoreStartupParameter.m_strName);
+ else
+ SetTitle(title);
+}
+
void wxCheatsWindow::Load_ARCodes()
{
using namespace ActionReplay;
m_CheckListBox_CheatsList->Clear();
+ if (!Core::IsRunning())
+ return;
+
indexList.clear();
size_t size = GetCodeListSize();
for (size_t i = 0; i < size; i++)
@@ -269,6 +281,11 @@ void wxCheatsWindow::Load_ARCodes()
}
}
+void wxCheatsWindow::Load_GeckoCodes()
+{
+ m_geckocode_panel->LoadCodes(m_gameini, Core::g_CoreStartupParameter.GetUniqueID(), true);
+}
+
void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED (event))
{
using namespace ActionReplay;
diff --git a/Source/Core/DolphinWX/Src/CheatsWindow.h b/Source/Core/DolphinWX/Src/CheatsWindow.h
index 293236e005..244e4d5b48 100644
--- a/Source/Core/DolphinWX/Src/CheatsWindow.h
+++ b/Source/Core/DolphinWX/Src/CheatsWindow.h
@@ -96,6 +96,7 @@ class wxCheatsWindow : public wxDialog
public:
wxCheatsWindow(wxWindow* const parent);
~wxCheatsWindow();
+ void UpdateGUI();
protected:
@@ -105,6 +106,7 @@ class wxCheatsWindow : public wxDialog
};
// --- GUI Controls ---
+ wxButton* button_apply;
wxNotebook *m_Notebook_Main;
wxPanel *m_Tab_Cheats;
@@ -134,6 +136,7 @@ class wxCheatsWindow : public wxDialog
void Init_ChildControls();
void Load_ARCodes();
+ void Load_GeckoCodes();
// --- Wx Events Handlers ---
diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp
index edbc45a50d..4ae51d78a1 100644
--- a/Source/Core/DolphinWX/Src/ConfigMain.cpp
+++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp
@@ -87,6 +87,7 @@ static const wxLanguage langIds[] =
#define SIDEV_STDCONT_STR _trans("Standard Controller")
#define SIDEV_STEERING_STR _trans("Steering Wheel")
+#define SIDEV_DANCEMAT_STR _trans("Dance Mat")
#define SIDEV_BONGO_STR _trans("TaruKonga (Bongos)")
#define SIDEV_GBA_STR "GBA"
#define SIDEV_AM_BB_STR _trans("AM-Baseboard")
@@ -388,6 +389,7 @@ void CConfigMain::InitializeGUIValues()
SIDevices.Add(_(DEV_NONE_STR));
SIDevices.Add(_(SIDEV_STDCONT_STR));
SIDevices.Add(_(SIDEV_STEERING_STR));
+ SIDevices.Add(_(SIDEV_DANCEMAT_STR));
SIDevices.Add(_(SIDEV_BONGO_STR));
SIDevices.Add(_(SIDEV_GBA_STR));
SIDevices.Add(_(SIDEV_AM_BB_STR));
@@ -443,15 +445,18 @@ void CConfigMain::InitializeGUIValues()
case SIDEVICE_GC_STEERING:
GCSIDevice[i]->SetStringSelection(SIDevices[2]);
break;
- case SIDEVICE_GC_TARUKONGA:
+ case SIDEVICE_DANCEMAT:
GCSIDevice[i]->SetStringSelection(SIDevices[3]);
break;
- case SIDEVICE_GC_GBA:
+ case SIDEVICE_GC_TARUKONGA:
GCSIDevice[i]->SetStringSelection(SIDevices[4]);
break;
- case SIDEVICE_AM_BASEBOARD:
+ case SIDEVICE_GC_GBA:
GCSIDevice[i]->SetStringSelection(SIDevices[5]);
break;
+ case SIDEVICE_AM_BASEBOARD:
+ GCSIDevice[i]->SetStringSelection(SIDevices[6]);
+ break;
default:
GCSIDevice[i]->SetStringSelection(SIDevices[0]);
break;
@@ -1103,6 +1108,8 @@ void CConfigMain::ChooseSIDevice(wxString deviceName, int deviceNum)
tempType = SIDEVICE_GC_CONTROLLER;
else if (!deviceName.compare(WXSTR_TRANS(SIDEV_STEERING_STR)))
tempType = SIDEVICE_GC_STEERING;
+ else if (!deviceName.compare(WXSTR_TRANS(SIDEV_DANCEMAT_STR)))
+ tempType = SIDEVICE_DANCEMAT;
else if (!deviceName.compare(WXSTR_TRANS(SIDEV_BONGO_STR)))
tempType = SIDEVICE_GC_TARUKONGA;
else if (!deviceName.compare(wxT(SIDEV_GBA_STR)))
diff --git a/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp b/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp
index 8b22166a81..63781008b3 100644
--- a/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp
+++ b/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp
@@ -34,8 +34,8 @@ FifoPlayerDlg::FifoPlayerDlg(wxWindow * const parent) :
{
CreateGUIControls();
- sMutex.lock();
- m_EvtHandler = GetEventHandler();
+ sMutex.lock();
+ m_EvtHandler = GetEventHandler();
sMutex.unlock();
FifoPlayer::GetInstance().SetFileLoadedCallback(FileLoaded);
@@ -55,7 +55,7 @@ FifoPlayerDlg::~FifoPlayerDlg()
m_ObjectToCtrl->Unbind(wxEVT_COMMAND_SPINCTRL_UPDATED, &FifoPlayerDlg::OnObjectTo, this);
m_EarlyMemoryUpdates->Unbind(wxEVT_COMMAND_CHECKBOX_CLICKED, &FifoPlayerDlg::OnCheckEarlyMemoryUpdates, this);
m_RecordStop->Unbind(wxEVT_COMMAND_BUTTON_CLICKED, &FifoPlayerDlg::OnRecordStop, this);
- m_Save->Unbind(wxEVT_COMMAND_BUTTON_CLICKED, &FifoPlayerDlg::OnSaveFile, this);
+ m_Save->Unbind(wxEVT_COMMAND_BUTTON_CLICKED, &FifoPlayerDlg::OnSaveFile, this);
m_FramesToRecordCtrl->Unbind(wxEVT_COMMAND_SPINCTRL_UPDATED, &FifoPlayerDlg::OnNumFramesToRecord, this);
m_Close->Unbind(wxEVT_COMMAND_BUTTON_CLICKED, &FifoPlayerDlg::OnCloseClick, this);
@@ -65,7 +65,7 @@ FifoPlayerDlg::~FifoPlayerDlg()
FifoPlayer::GetInstance().SetFrameWrittenCallback(NULL);
- sMutex.lock();
+ sMutex.lock();
m_EvtHandler = NULL;
sMutex.unlock();
}
@@ -192,7 +192,8 @@ void FifoPlayerDlg::CreateGUIControls()
m_FramesToRecordLabel->Wrap(-1);
sRecordingOptions->Add(m_FramesToRecordLabel, 0, wxALL, 5);
- m_FramesToRecordCtrl = new wxSpinCtrl(m_RecordPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 10000, 1);
+ wxString initialNum = wxString::Format(_T("%d"), m_FramesToRecord);
+ m_FramesToRecordCtrl = new wxSpinCtrl(m_RecordPage, wxID_ANY, initialNum, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 10000, 1);
sRecordingOptions->Add(m_FramesToRecordCtrl, 0, wxALL, 5);
sRecordPage->Add(sRecordingOptions, 0, wxEXPAND, 5);
@@ -252,9 +253,7 @@ void FifoPlayerDlg::CreateGUIControls()
m_findNext = new wxButton(m_AnalyzePage, wxID_ANY, _("Find next"));
m_findPrevious = new wxButton(m_AnalyzePage, wxID_ANY, _("Find previous"));
- m_beginSearch->Disable();
- m_findNext->Disable();
- m_findPrevious->Disable();
+ ResetSearch();
sSearchButtons->Add(m_beginSearch, 0, wxALL, 5);
sSearchButtons->Add(m_findNext, 0, wxALL, 5);
@@ -407,8 +406,8 @@ void FifoPlayerDlg::OnRecordStop(wxCommandEvent& WXUNUSED(event))
// Then stop recording
recorder.StopRecording();
- // and disable the button to stop recording
- m_RecordStop->Disable();
+ // and change the button label accordingly.
+ m_RecordStop->SetLabel(_("Record"));
}
else // Recorder is actually about to start recording
{
@@ -499,16 +498,12 @@ void FifoPlayerDlg::OnBeginSearch(wxCommandEvent& event)
ChangeSearchResult(0);
m_beginSearch->Disable();
- m_findNext->Enable();
- m_findPrevious->Enable();
m_numResultsText->SetLabel(wxString::Format(_("Found %d results for \'"), search_results.size()) + m_searchField->GetValue() + _("\'"));
}
void FifoPlayerDlg::OnSearchFieldTextChanged(wxCommandEvent& event)
{
- m_beginSearch->Enable(m_searchField->GetLineLength(0) > 0);
- m_findNext->Disable();
- m_findPrevious->Disable();
+ ResetSearch();
}
void FifoPlayerDlg::OnFindNextClick(wxCommandEvent& event)
@@ -551,7 +546,7 @@ void FifoPlayerDlg::OnFindPreviousClick(wxCommandEvent& event)
void FifoPlayerDlg::ChangeSearchResult(unsigned int result_idx)
{
- if (search_results.size() > result_idx)
+ if (result_idx < search_results.size()) // if index is valid
{
m_search_result_idx = result_idx;
int prev_frame = m_framesList->GetSelection();
@@ -577,6 +572,9 @@ void FifoPlayerDlg::ChangeSearchResult(unsigned int result_idx)
ev.SetInt(m_objectCmdList->GetSelection());
OnObjectCmdListSelectionChanged(ev);
}
+
+ m_findNext->Enable(result_idx+1 < search_results.size());
+ m_findPrevious->Enable(result_idx != 0);
}
else if (search_results.size())
{
@@ -584,6 +582,15 @@ void FifoPlayerDlg::ChangeSearchResult(unsigned int result_idx)
}
}
+void FifoPlayerDlg::ResetSearch()
+{
+ m_beginSearch->Enable(m_searchField->GetLineLength(0) > 0);
+ m_findNext->Disable();
+ m_findPrevious->Disable();
+
+ search_results.clear();
+}
+
void FifoPlayerDlg::OnFrameListSelectionChanged(wxCommandEvent& event)
{
FifoPlayer& player = FifoPlayer::GetInstance();
@@ -600,6 +607,8 @@ void FifoPlayerDlg::OnFrameListSelectionChanged(wxCommandEvent& event)
wxCommandEvent ev = wxCommandEvent(wxEVT_COMMAND_LISTBOX_SELECTED);
ev.SetInt(-1);
OnObjectListSelectionChanged(ev);
+
+ ResetSearch();
}
void FifoPlayerDlg::OnObjectListSelectionChanged(wxCommandEvent& event)
@@ -727,6 +736,8 @@ void FifoPlayerDlg::OnObjectListSelectionChanged(wxCommandEvent& event)
wxCommandEvent ev = wxCommandEvent(wxEVT_COMMAND_LISTBOX_SELECTED);
ev.SetInt(-1);
OnObjectCmdListSelectionChanged(ev);
+
+ ResetSearch();
}
void FifoPlayerDlg::OnObjectCmdListSelectionChanged(wxCommandEvent& event)
diff --git a/Source/Core/DolphinWX/Src/FifoPlayerDlg.h b/Source/Core/DolphinWX/Src/FifoPlayerDlg.h
index 9b0098a92e..6f4a8074b9 100644
--- a/Source/Core/DolphinWX/Src/FifoPlayerDlg.h
+++ b/Source/Core/DolphinWX/Src/FifoPlayerDlg.h
@@ -37,6 +37,7 @@ private:
void OnFindPreviousClick(wxCommandEvent& event);
void OnSearchFieldTextChanged(wxCommandEvent& event);
void ChangeSearchResult(unsigned int result_idx);
+ void ResetSearch();
void OnRecordingFinished(wxEvent& event);
void OnFrameWritten(wxEvent& event);
diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp
index 2ed76f6214..1e0e0c756c 100644
--- a/Source/Core/DolphinWX/Src/Frame.cpp
+++ b/Source/Core/DolphinWX/Src/Frame.cpp
@@ -204,13 +204,14 @@ EVT_MENU_RANGE(IDM_LOGWINDOW, IDM_VIDEOWINDOW, CFrame::OnToggleWindow)
EVT_MENU(IDM_PURGECACHE, CFrame::GameListChanged)
-EVT_MENU(IDM_LOADLASTSTATE, CFrame::OnLoadLastState)
+EVT_MENU(IDM_SAVEFIRSTSTATE, CFrame::OnSaveFirstState)
EVT_MENU(IDM_UNDOLOADSTATE, CFrame::OnUndoLoadState)
EVT_MENU(IDM_UNDOSAVESTATE, CFrame::OnUndoSaveState)
EVT_MENU(IDM_LOADSTATEFILE, CFrame::OnLoadStateFromFile)
EVT_MENU(IDM_SAVESTATEFILE, CFrame::OnSaveStateToFile)
EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT8, CFrame::OnLoadState)
+EVT_MENU_RANGE(IDM_LOADLAST1, IDM_LOADLAST8, CFrame::OnLoadLastState)
EVT_MENU_RANGE(IDM_SAVESLOT1, IDM_SAVESLOT8, CFrame::OnSaveState)
EVT_MENU_RANGE(IDM_FRAMESKIP0, IDM_FRAMESKIP9, CFrame::OnFrameSkip)
EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive)
@@ -719,104 +720,56 @@ int GetCmdForHotkey(unsigned int key)
{
switch (key)
{
- case HK_OPEN:
- return wxID_OPEN;
+ case HK_OPEN: return wxID_OPEN;
+ case HK_CHANGE_DISC: return IDM_CHANGEDISC;
+ case HK_REFRESH_LIST: return wxID_REFRESH;
+ case HK_PLAY_PAUSE: return IDM_PLAY;
+ case HK_STOP: return IDM_STOP;
+ case HK_RESET: return IDM_RESET;
+ case HK_FRAME_ADVANCE: return IDM_FRAMESTEP;
+ case HK_START_RECORDING: return IDM_RECORD;
+ case HK_PLAY_RECORDING: return IDM_PLAYRECORD;
+ case HK_EXPORT_RECORDING: return IDM_RECORDEXPORT;
+ case HK_READ_ONLY_MODE: return IDM_RECORDREADONLY;
+ case HK_FULLSCREEN: return IDM_TOGGLE_FULLSCREEN;
+ case HK_SCREENSHOT: return IDM_SCREENSHOT;
+ case HK_EXIT: return wxID_EXIT;
- case HK_CHANGE_DISC:
- return IDM_CHANGEDISC;
+ case HK_WIIMOTE1_CONNECT: return IDM_CONNECT_WIIMOTE1;
+ case HK_WIIMOTE2_CONNECT: return IDM_CONNECT_WIIMOTE2;
+ case HK_WIIMOTE3_CONNECT: return IDM_CONNECT_WIIMOTE3;
+ case HK_WIIMOTE4_CONNECT: return IDM_CONNECT_WIIMOTE4;
- case HK_REFRESH_LIST:
- return wxID_REFRESH;
+ case HK_LOAD_STATE_SLOT_1: return IDM_LOADSLOT1;
+ case HK_LOAD_STATE_SLOT_2: return IDM_LOADSLOT2;
+ case HK_LOAD_STATE_SLOT_3: return IDM_LOADSLOT3;
+ case HK_LOAD_STATE_SLOT_4: return IDM_LOADSLOT4;
+ case HK_LOAD_STATE_SLOT_5: return IDM_LOADSLOT5;
+ case HK_LOAD_STATE_SLOT_6: return IDM_LOADSLOT6;
+ case HK_LOAD_STATE_SLOT_7: return IDM_LOADSLOT7;
+ case HK_LOAD_STATE_SLOT_8: return IDM_LOADSLOT8;
- case HK_PLAY_PAUSE:
- return IDM_PLAY;
+ case HK_SAVE_STATE_SLOT_1: return IDM_SAVESLOT1;
+ case HK_SAVE_STATE_SLOT_2: return IDM_SAVESLOT2;
+ case HK_SAVE_STATE_SLOT_3: return IDM_SAVESLOT3;
+ case HK_SAVE_STATE_SLOT_4: return IDM_SAVESLOT4;
+ case HK_SAVE_STATE_SLOT_5: return IDM_SAVESLOT5;
+ case HK_SAVE_STATE_SLOT_6: return IDM_SAVESLOT6;
+ case HK_SAVE_STATE_SLOT_7: return IDM_SAVESLOT7;
+ case HK_SAVE_STATE_SLOT_8: return IDM_SAVESLOT8;
- case HK_STOP:
- return IDM_STOP;
+ case HK_LOAD_LAST_STATE_1: return IDM_LOADLAST1;
+ case HK_LOAD_LAST_STATE_2: return IDM_LOADLAST2;
+ case HK_LOAD_LAST_STATE_3: return IDM_LOADLAST3;
+ case HK_LOAD_LAST_STATE_4: return IDM_LOADLAST4;
+ case HK_LOAD_LAST_STATE_5: return IDM_LOADLAST5;
+ case HK_LOAD_LAST_STATE_6: return IDM_LOADLAST6;
+ case HK_LOAD_LAST_STATE_7: return IDM_LOADLAST7;
+ case HK_LOAD_LAST_STATE_8: return IDM_LOADLAST8;
- case HK_RESET:
- return IDM_RESET;
-
- case HK_FRAME_ADVANCE:
- return IDM_FRAMESTEP;
-
- case HK_START_RECORDING:
- return IDM_RECORD;
-
- case HK_PLAY_RECORDING:
- return IDM_PLAYRECORD;
-
- case HK_EXPORT_RECORDING:
- return IDM_RECORDEXPORT;
-
- case HK_READ_ONLY_MODE:
- return IDM_RECORDREADONLY;
-
- case HK_FULLSCREEN:
- return IDM_TOGGLE_FULLSCREEN;
-
- case HK_SCREENSHOT:
- return IDM_SCREENSHOT;
-
- case HK_WIIMOTE1_CONNECT:
- return IDM_CONNECT_WIIMOTE1;
-
- case HK_WIIMOTE2_CONNECT:
- return IDM_CONNECT_WIIMOTE2;
-
- case HK_WIIMOTE3_CONNECT:
- return IDM_CONNECT_WIIMOTE3;
-
- case HK_WIIMOTE4_CONNECT:
- return IDM_CONNECT_WIIMOTE4;
-
- case HK_LOAD_STATE_SLOT_1:
- return IDM_LOADSLOT1;
-
- case HK_LOAD_STATE_SLOT_2:
- return IDM_LOADSLOT2;
-
- case HK_LOAD_STATE_SLOT_3:
- return IDM_LOADSLOT3;
-
- case HK_LOAD_STATE_SLOT_4:
- return IDM_LOADSLOT4;
-
- case HK_LOAD_STATE_SLOT_5:
- return IDM_LOADSLOT5;
-
- case HK_LOAD_STATE_SLOT_6:
- return IDM_LOADSLOT6;
-
- case HK_LOAD_STATE_SLOT_7:
- return IDM_LOADSLOT7;
-
- case HK_LOAD_STATE_SLOT_8:
- return IDM_LOADSLOT8;
-
- case HK_SAVE_STATE_SLOT_1:
- return IDM_SAVESLOT1;
-
- case HK_SAVE_STATE_SLOT_2:
- return IDM_SAVESLOT2;
-
- case HK_SAVE_STATE_SLOT_3:
- return IDM_SAVESLOT3;
-
- case HK_SAVE_STATE_SLOT_4:
- return IDM_SAVESLOT4;
-
- case HK_SAVE_STATE_SLOT_5:
- return IDM_SAVESLOT5;
-
- case HK_SAVE_STATE_SLOT_6:
- return IDM_SAVESLOT6;
-
- case HK_SAVE_STATE_SLOT_7:
- return IDM_SAVESLOT7;
-
- case HK_SAVE_STATE_SLOT_8:
- return IDM_SAVESLOT8;
+ case HK_SAVE_FIRST_STATE: return IDM_SAVEFIRSTSTATE;
+ case HK_UNDO_LOAD_STATE: return IDM_UNDOLOADSTATE;
+ case HK_UNDO_SAVE_STATE: return IDM_UNDOSAVESTATE;
}
return -1;
@@ -859,6 +812,8 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
// Screenshot hotkey
else if (IsHotkey(event, HK_SCREENSHOT))
Core::SaveScreenShot();
+ else if (IsHotkey(event, HK_EXIT))
+ wxPostEvent(this, wxCommandEvent(wxID_EXIT));
// Wiimote connect and disconnect hotkeys
else if (IsHotkey(event, HK_WIIMOTE1_CONNECT))
WiimoteId = 0;
@@ -868,28 +823,6 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
WiimoteId = 2;
else if (IsHotkey(event, HK_WIIMOTE4_CONNECT))
WiimoteId = 3;
- // State save and state load hotkeys
- /*else if (event.GetKeyCode() >= WXK_F1 && event.GetKeyCode() <= WXK_F8)
- {
- int slot_number = event.GetKeyCode() - WXK_F1 + 1;
- if (event.GetModifiers() == wxMOD_NONE)
- State::Load(slot_number);
- else if (event.GetModifiers() == wxMOD_SHIFT)
- State::Save(slot_number);
- else
- event.Skip();
- }*/
- else if (event.GetKeyCode() == WXK_F11 && event.GetModifiers() == wxMOD_NONE)
- State::LoadLastSaved();
- else if (event.GetKeyCode() == WXK_F12)
- {
- if (event.GetModifiers() == wxMOD_NONE)
- State::UndoSaveState();
- else if (event.GetModifiers() == wxMOD_SHIFT)
- State::UndoLoadState();
- else
- event.Skip();
- }
else
{
unsigned int i = NUM_HOTKEYS;
diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h
index 6657c62013..0a29fffd37 100644
--- a/Source/Core/DolphinWX/Src/Frame.h
+++ b/Source/Core/DolphinWX/Src/Frame.h
@@ -289,6 +289,7 @@ private:
void OnLoadStateFromFile(wxCommandEvent& event);
void OnSaveStateToFile(wxCommandEvent& event);
void OnLoadLastState(wxCommandEvent& event);
+ void OnSaveFirstState(wxCommandEvent& event);
void OnUndoLoadState(wxCommandEvent& event);
void OnUndoSaveState(wxCommandEvent& event);
diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp
index ef0aa81e9d..8607fdb110 100644
--- a/Source/Core/DolphinWX/Src/FrameTools.cpp
+++ b/Source/Core/DolphinWX/Src/FrameTools.cpp
@@ -150,26 +150,25 @@ void CFrame::CreateMenu()
emulationMenu->Append(IDM_SAVESTATE, _("Sa&ve State"), saveMenu);
saveMenu->Append(IDM_SAVESTATEFILE, _("Save State..."));
- loadMenu->Append(IDM_UNDOSAVESTATE, _("Last Overwritten State") + wxString(wxT("\tF12")));
+ saveMenu->Append(IDM_SAVEFIRSTSTATE, GetMenuLabel(HK_SAVE_FIRST_STATE));
+ loadMenu->Append(IDM_UNDOSAVESTATE, GetMenuLabel(HK_UNDO_SAVE_STATE));
saveMenu->AppendSeparator();
loadMenu->Append(IDM_LOADSTATEFILE, _("Load State..."));
-
- // Reserve F11 for the "step into" function in the debugger
- if (g_pCodeWindow)
- loadMenu->Append(IDM_LOADLASTSTATE, _("Last Saved State"));
- else
- loadMenu->Append(IDM_LOADLASTSTATE, _("Last Saved State") + wxString(wxT("\tF11")));
- loadMenu->Append(IDM_UNDOLOADSTATE, _("Undo Load State") + wxString(wxT("\tShift+F12")));
+ loadMenu->Append(IDM_UNDOLOADSTATE, GetMenuLabel(HK_UNDO_LOAD_STATE));
loadMenu->AppendSeparator();
- for (int i = 1; i <= 8; i++)
+ for (unsigned int i = 1; i <= State::NUM_STATES; i++)
{
loadMenu->Append(IDM_LOADSLOT1 + i - 1, GetMenuLabel(HK_LOAD_STATE_SLOT_1 + i - 1));
saveMenu->Append(IDM_SAVESLOT1 + i - 1, GetMenuLabel(HK_SAVE_STATE_SLOT_1 + i - 1));
}
+ loadMenu->AppendSeparator();
+ for (unsigned int i = 1; i <= State::NUM_STATES; i++)
+ loadMenu->Append(IDM_LOADLAST1 + i - 1, GetMenuLabel(HK_LOAD_LAST_STATE_1 + i - 1));
+
m_MenuBar->Append(emulationMenu, _("&Emulation"));
// Options menu
@@ -360,6 +359,9 @@ wxString CFrame::GetMenuLabel(int Id)
case HK_SCREENSHOT:
Label = _("Take Screenshot");
break;
+ case HK_EXIT:
+ Label = _("Exit");
+ break;
case HK_WIIMOTE1_CONNECT:
case HK_WIIMOTE2_CONNECT:
@@ -393,6 +395,22 @@ wxString CFrame::GetMenuLabel(int Id)
Id - HK_SAVE_STATE_SLOT_1 + 1);
break;
+ case HK_LOAD_LAST_STATE_1:
+ case HK_LOAD_LAST_STATE_2:
+ case HK_LOAD_LAST_STATE_3:
+ case HK_LOAD_LAST_STATE_4:
+ case HK_LOAD_LAST_STATE_5:
+ case HK_LOAD_LAST_STATE_6:
+ case HK_LOAD_LAST_STATE_7:
+ case HK_LOAD_LAST_STATE_8:
+ Label = wxString::Format(_("Last %i"),
+ Id - HK_LOAD_LAST_STATE_1 + 1);
+ break;
+
+ case HK_SAVE_FIRST_STATE: Label = wxString("Save Oldest State"); break;
+ case HK_UNDO_LOAD_STATE: Label = wxString("Undo Load State"); break;
+ case HK_UNDO_SAVE_STATE: Label = wxString("Undo Save State"); break;
+
default:
Label = wxString::Format(_("Undefined %i"), Id);
}
@@ -780,7 +798,7 @@ void CFrame::OnRenderParentResize(wxSizeEvent& event)
void CFrame::ToggleDisplayMode(bool bFullscreen)
{
#ifdef _WIN32
- if (bFullscreen)
+ if (bFullscreen && SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution != "Auto")
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
@@ -799,7 +817,8 @@ void CFrame::ToggleDisplayMode(bool bFullscreen)
ChangeDisplaySettings(NULL, CDS_FULLSCREEN);
}
#elif defined(HAVE_XRANDR) && HAVE_XRANDR
- m_XRRConfig->ToggleDisplayMode(bFullscreen);
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution != "Auto")
+ m_XRRConfig->ToggleDisplayMode(bFullscreen);
#elif defined __APPLE__
if(bFullscreen)
CGDisplayHideCursor(CGMainDisplayID());
@@ -1115,6 +1134,7 @@ void CFrame::OnConfigMain(wxCommandEvent& WXUNUSED (event))
CConfigMain ConfigMain(this);
if (ConfigMain.ShowModal() == wxID_OK)
m_GameListCtrl->Update();
+ UpdateGUI();
}
void CFrame::OnConfigGFX(wxCommandEvent& WXUNUSED (event))
@@ -1437,10 +1457,20 @@ void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event))
State::SaveAs(WxStrToStr(path));
}
-void CFrame::OnLoadLastState(wxCommandEvent& WXUNUSED (event))
+void CFrame::OnLoadLastState(wxCommandEvent& event)
{
if (Core::IsRunningAndStarted())
- State::LoadLastSaved();
+ {
+ int id = event.GetId();
+ int slot = id - IDM_LOADLAST1 + 1;
+ State::LoadLastSaved(slot);
+ }
+}
+
+void CFrame::OnSaveFirstState(wxCommandEvent& WXUNUSED(event))
+{
+ if (Core::GetState() != Core::CORE_UNINITIALIZED)
+ State::SaveFirstSaved();
}
void CFrame::OnUndoLoadState(wxCommandEvent& WXUNUSED (event))
@@ -1540,6 +1570,9 @@ void CFrame::UpdateGUI()
if (DiscIO::CNANDContentManager::Access().GetNANDLoader(TITLEID_SYSMENU).IsValid())
GetMenuBar()->FindItem(IDM_LOAD_WII_MENU)->Enable(!Initialized);
+ // Tools
+ GetMenuBar()->FindItem(IDM_CHEATS)->Enable(SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats);
+
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(RunningWii);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(RunningWii);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Enable(RunningWii);
@@ -1647,6 +1680,15 @@ void CFrame::UpdateGUI()
// Commit changes to manager
m_Mgr->Update();
+
+ // Update non-modal windows
+ if (g_CheatsWindow)
+ {
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
+ g_CheatsWindow->UpdateGUI();
+ else
+ g_CheatsWindow->Close();
+ }
}
void CFrame::UpdateGameList()
diff --git a/Source/Core/DolphinWX/Src/GCMicDlg.h b/Source/Core/DolphinWX/Src/GCMicDlg.h
index ee6933b7c5..7d5d88b6dd 100644
--- a/Source/Core/DolphinWX/Src/GCMicDlg.h
+++ b/Source/Core/DolphinWX/Src/GCMicDlg.h
@@ -2,8 +2,8 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
-#ifndef __HOTKEYDIALOG_h__
-#define __HOTKEYDIALOG_h__
+#ifndef __GCMICDIALOG_h__
+#define __GCMICDIALOG_h__
#include
#include
diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp b/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp
index aa26c40b6f..6c12c1156c 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp
+++ b/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp
@@ -52,7 +52,11 @@ bool cInterfaceEGL::Create(void *&window_handle)
EGL_BLUE_SIZE, 8,
EGL_DEPTH_SIZE, 24,
#ifdef USE_GLES
+#ifdef USE_GLES3
+ EGL_RENDERABLE_TYPE, (1 << 6) /* EGL_OPENGL_ES3_BIT */,
+#else
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+#endif
#else
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
#endif
diff --git a/Source/Core/DolphinWX/Src/GLInterface/GLX.cpp b/Source/Core/DolphinWX/Src/GLInterface/GLX.cpp
index 84a753c784..929d365081 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/GLX.cpp
+++ b/Source/Core/DolphinWX/Src/GLInterface/GLX.cpp
@@ -25,7 +25,7 @@
// Show the current FPS
void cInterfaceGLX::UpdateFPSDisplay(const char *text)
{
- XStoreName(GLWin.dpy, GLWin.win, text);
+ XStoreName(GLWin.evdpy, GLWin.win, text);
}
void cInterfaceGLX::SwapInterval(int Interval)
@@ -136,7 +136,7 @@ bool cInterfaceGLX::MakeCurrent()
#if defined(HAVE_WX) && (HAVE_WX)
Host_GetRenderWindowSize(GLWin.x, GLWin.y,
(int&)GLWin.width, (int&)GLWin.height);
- XMoveResizeWindow(GLWin.dpy, GLWin.win, GLWin.x, GLWin.y,
+ XMoveResizeWindow(GLWin.evdpy, GLWin.win, GLWin.x, GLWin.y,
GLWin.width, GLWin.height);
#endif
return glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx);
diff --git a/Source/Core/DolphinWX/Src/GLInterface/Platform.cpp b/Source/Core/DolphinWX/Src/GLInterface/Platform.cpp
index 83f064615c..64e32591d8 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/Platform.cpp
+++ b/Source/Core/DolphinWX/Src/GLInterface/Platform.cpp
@@ -115,7 +115,10 @@ out:
#if HAVE_X11
if (selected_platform != EGL_PLATFORM_X11) {
if (GLWin.dpy)
+ {
XCloseDisplay(GLWin.dpy);
+ XCloseDisplay(GLWin.evdpy);
+ }
}
#endif
if (selected_platform == EGL_PLATFORM_NONE)
diff --git a/Source/Core/DolphinWX/Src/GLInterface/X11_Util.cpp b/Source/Core/DolphinWX/Src/GLInterface/X11_Util.cpp
index dd04ee0c73..f6e678151f 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/X11_Util.cpp
+++ b/Source/Core/DolphinWX/Src/GLInterface/X11_Util.cpp
@@ -24,9 +24,9 @@
#if USE_EGL
bool cXInterface::ServerConnect(void)
{
- GLWin.evdpy = XOpenDisplay(NULL);
+ GLWin.dpy = XOpenDisplay(NULL);
- if (!GLWin.evdpy)
+ if (!GLWin.dpy)
return false;
return true;
@@ -39,7 +39,7 @@ bool cXInterface::Initialize(void *config)
int num_visuals;
EGLint vid;
- if (!GLWin.evdpy) {
+ if (!GLWin.dpy) {
printf("Error: couldn't open X display\n");
return false;
}
@@ -51,7 +51,7 @@ bool cXInterface::Initialize(void *config)
/* The X window visual must match the EGL config */
visTemplate.visualid = vid;
- GLWin.vi = XGetVisualInfo(GLWin.evdpy, VisualIDMask, &visTemplate, &num_visuals);
+ GLWin.vi = XGetVisualInfo(GLWin.dpy, VisualIDMask, &visTemplate, &num_visuals);
if (!GLWin.vi) {
printf("Error: couldn't get X visual\n");
exit(1);
@@ -64,12 +64,12 @@ bool cXInterface::Initialize(void *config)
GLWin.width = _twidth;
GLWin.height = _theight;
- GLWin.dpy = XOpenDisplay(NULL);
+ GLWin.evdpy = XOpenDisplay(NULL);
GLWin.parent = GLWin.win;
- GLWin.screen = DefaultScreen(GLWin.evdpy);
+ GLWin.screen = DefaultScreen(GLWin.dpy);
if (GLWin.parent == 0)
- GLWin.parent = RootWindow(GLWin.evdpy, GLWin.screen);
+ GLWin.parent = RootWindow(GLWin.dpy, GLWin.screen);
/* Set initial projection/viewing transformation.
* We can't be sure we'll get a ConfigureNotify event when the window
@@ -82,7 +82,7 @@ bool cXInterface::Initialize(void *config)
void *cXInterface::EGLGetDisplay(void)
{
- return eglGetDisplay(GLWin.evdpy);
+ return eglGetDisplay(GLWin.dpy);
}
void *cXInterface::CreateWindow(void)
@@ -90,22 +90,22 @@ void *cXInterface::CreateWindow(void)
Atom wmProtocols[1];
// Setup window attributes
- GLWin.attr.colormap = XCreateColormap(GLWin.dpy,
+ GLWin.attr.colormap = XCreateColormap(GLWin.evdpy,
GLWin.parent, GLWin.vi->visual, AllocNone);
GLWin.attr.event_mask = KeyPressMask | StructureNotifyMask | FocusChangeMask;
- GLWin.attr.background_pixel = BlackPixel(GLWin.dpy, GLWin.screen);
+ GLWin.attr.background_pixel = BlackPixel(GLWin.evdpy, GLWin.screen);
GLWin.attr.border_pixel = 0;
// Create the window
- GLWin.win = XCreateWindow(GLWin.dpy, GLWin.parent,
+ GLWin.win = XCreateWindow(GLWin.evdpy, GLWin.parent,
GLWin.x, GLWin.y, GLWin.width, GLWin.height, 0,
GLWin.vi->depth, InputOutput, GLWin.vi->visual,
CWBorderPixel | CWBackPixel | CWColormap | CWEventMask, &GLWin.attr);
- wmProtocols[0] = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True);
- XSetWMProtocols(GLWin.dpy, GLWin.win, wmProtocols, 1);
- XSetStandardProperties(GLWin.dpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL);
- XMapRaised(GLWin.dpy, GLWin.win);
- XSync(GLWin.dpy, True);
+ wmProtocols[0] = XInternAtom(GLWin.evdpy, "WM_DELETE_WINDOW", True);
+ XSetWMProtocols(GLWin.evdpy, GLWin.win, wmProtocols, 1);
+ XSetStandardProperties(GLWin.evdpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL);
+ XMapRaised(GLWin.evdpy, GLWin.win);
+ XSync(GLWin.evdpy, True);
GLWin.xEventThread = std::thread(&cXInterface::XEventThread, this);
// Control window size and picture scaling
@@ -116,16 +116,16 @@ void *cXInterface::CreateWindow(void)
void cXInterface::DestroyWindow(void)
{
- XDestroyWindow(GLWin.dpy, GLWin.win);
+ XDestroyWindow(GLWin.evdpy, GLWin.win);
GLWin.win = 0;
if (GLWin.xEventThread.joinable())
GLWin.xEventThread.join();
- XFreeColormap(GLWin.dpy, GLWin.attr.colormap);
+ XFreeColormap(GLWin.evdpy, GLWin.attr.colormap);
}
void cXInterface::UpdateFPSDisplay(const char *text)
{
- XStoreName(GLWin.dpy, GLWin.win, text);
+ XStoreName(GLWin.evdpy, GLWin.win, text);
}
void cXInterface::XEventThread()
@@ -157,7 +157,7 @@ void cX11Window::CreateXWindow(void)
void cX11Window::DestroyXWindow(void)
{
- XUnmapWindow(GLWin.dpy, GLWin.win);
+ XUnmapWindow(GLWin.evdpy, GLWin.win);
GLWin.win = 0;
if (GLWin.xEventThread.joinable())
GLWin.xEventThread.join();
@@ -175,9 +175,9 @@ void cX11Window::XEventThread()
{
XEvent event;
KeySym key;
- for (int num_events = XPending(GLWin.dpy); num_events > 0; num_events--)
+ for (int num_events = XPending(GLWin.evdpy); num_events > 0; num_events--)
{
- XNextEvent(GLWin.dpy, &event);
+ XNextEvent(GLWin.evdpy, &event);
switch(event.type) {
case KeyPress:
key = XLookupKeysym((XKeyEvent*)&event, 0);
@@ -305,17 +305,17 @@ void cX11Window::XEventThread()
case ConfigureNotify:
Window winDummy;
unsigned int borderDummy, depthDummy;
- XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
+ XGetGeometry(GLWin.evdpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
&GLWin.width, &GLWin.height, &borderDummy, &depthDummy);
GLInterface->SetBackBufferDimensions(GLWin.width, GLWin.height);
break;
case ClientMessage:
if ((unsigned long) event.xclient.data.l[0] ==
- XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", False))
+ XInternAtom(GLWin.evdpy, "WM_DELETE_WINDOW", False))
Host_Message(WM_USER_STOP);
if ((unsigned long) event.xclient.data.l[0] ==
- XInternAtom(GLWin.dpy, "RESIZE", False))
- XMoveResizeWindow(GLWin.dpy, GLWin.win,
+ XInternAtom(GLWin.evdpy, "RESIZE", False))
+ XMoveResizeWindow(GLWin.evdpy, GLWin.win,
event.xclient.data.l[1], event.xclient.data.l[2],
event.xclient.data.l[3], event.xclient.data.l[4]);
break;
diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp
index 9f96956abc..39130bcf8e 100644
--- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp
+++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "GeckoCodeDiag.h"
+#include "Core.h"
#include "WxUtils.h"
#include
@@ -41,7 +42,8 @@ CodeConfigPanel::CodeConfigPanel(wxWindow* const parent)
// button sizer
wxBoxSizer* const sizer_buttons = new wxBoxSizer(wxHORIZONTAL);
- wxButton* const btn_download = new wxButton(this, -1, _("Download Codes (WiiRD Database)"), wxDefaultPosition, wxSize(128, -1));
+ btn_download = new wxButton(this, -1, _("Download Codes (WiiRD Database)"), wxDefaultPosition, wxSize(128, -1));
+ btn_download->Enable(false);
btn_download->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &CodeConfigPanel::DownloadCodes, this);
sizer_buttons->AddStretchSpacer(1);
sizer_buttons->Add(btn_download, 1, wxEXPAND);
@@ -58,8 +60,11 @@ CodeConfigPanel::CodeConfigPanel(wxWindow* const parent)
SetSizerAndFit(sizer_main);
}
-void CodeConfigPanel::UpdateCodeList()
+void CodeConfigPanel::UpdateCodeList(bool checkRunning)
{
+ // disable the button if it doesn't have an effect
+ btn_download->Enable((!checkRunning || Core::IsRunning()) && !m_gameid.empty());
+
m_listbox_gcodes->Clear();
// add the codes to the listbox
std::vector::const_iterator
@@ -76,14 +81,15 @@ void CodeConfigPanel::UpdateCodeList()
UpdateInfoBox(evt);
}
-void CodeConfigPanel::LoadCodes(const IniFile& inifile, const std::string& gameid)
+void CodeConfigPanel::LoadCodes(const IniFile& inifile, const std::string& gameid, bool checkRunning)
{
m_gameid = gameid;
m_gcodes.clear();
- Gecko::LoadCodes(inifile, m_gcodes);
+ if (!checkRunning || Core::IsRunning())
+ Gecko::LoadCodes(inifile, m_gcodes);
- UpdateCodeList();
+ UpdateCodeList(checkRunning);
}
void CodeConfigPanel::ToggleCode(wxCommandEvent& evt)
@@ -277,9 +283,8 @@ void CodeConfigPanel::DownloadCodes(wxCommandEvent&)
break;
}
- // code with this name+creator exists
- if (existing_gcodes_iter->name == gcodes_iter->name &&
- existing_gcodes_iter->creator == gcodes_iter->creator)
+ // code exists
+ if (existing_gcodes_iter->Compare(*gcodes_iter))
break;
}
}
diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.h b/Source/Core/DolphinWX/Src/GeckoCodeDiag.h
index 8a59e09ce2..0140966c5e 100644
--- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.h
+++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.h
@@ -20,7 +20,7 @@ public:
CodeConfigPanel(wxWindow* const parent);
- void LoadCodes(const IniFile& inifile, const std::string& gameid = "");
+ void LoadCodes(const IniFile& inifile, const std::string& gameid = "", bool checkRunning = false);
const std::vector& GetCodes() const { return m_gcodes; }
protected:
@@ -29,7 +29,7 @@ protected:
void DownloadCodes(wxCommandEvent&);
//void ApplyChanges(wxCommandEvent&);
- void UpdateCodeList();
+ void UpdateCodeList(bool checkRunning = false);
private:
std::vector m_gcodes;
@@ -44,7 +44,7 @@ private:
wxTextCtrl *textctrl_notes;
wxListBox *listbox_codes;
} m_infobox;
-
+ wxButton* btn_download;
};
diff --git a/Source/Core/DolphinWX/Src/Globals.h b/Source/Core/DolphinWX/Src/Globals.h
index 8229af059a..144eafe40f 100644
--- a/Source/Core/DolphinWX/Src/Globals.h
+++ b/Source/Core/DolphinWX/Src/Globals.h
@@ -25,7 +25,7 @@ enum
{
IDM_LOADSTATE = 200, // File menu
IDM_SAVESTATE,
- IDM_LOADLASTSTATE,
+ IDM_SAVEFIRSTSTATE,
IDM_UNDOLOADSTATE,
IDM_UNDOSAVESTATE,
IDM_LOADSTATEFILE,
@@ -46,6 +46,14 @@ enum
IDM_LOADSLOT6,
IDM_LOADSLOT7,
IDM_LOADSLOT8,
+ IDM_LOADLAST1,
+ IDM_LOADLAST2,
+ IDM_LOADLAST3,
+ IDM_LOADLAST4,
+ IDM_LOADLAST5,
+ IDM_LOADLAST6,
+ IDM_LOADLAST7,
+ IDM_LOADLAST8,
IDM_FRAMESKIP0,
IDM_FRAMESKIP1,
IDM_FRAMESKIP2,
diff --git a/Source/Core/DolphinWX/Src/HotkeyDlg.cpp b/Source/Core/DolphinWX/Src/HotkeyDlg.cpp
index f841b412c6..5ee94deb59 100644
--- a/Source/Core/DolphinWX/Src/HotkeyDlg.cpp
+++ b/Source/Core/DolphinWX/Src/HotkeyDlg.cpp
@@ -179,6 +179,7 @@ void HotkeyConfigDialog::CreateHotkeyGUIControls(void)
_("Toggle Fullscreen"),
_("Take Screenshot"),
+ _("Exit"),
_("Connect Wiimote 1"),
_("Connect Wiimote 2"),
@@ -201,7 +202,20 @@ void HotkeyConfigDialog::CreateHotkeyGUIControls(void)
_("Save State Slot 5"),
_("Save State Slot 6"),
_("Save State Slot 7"),
- _("Save State Slot 8")
+ _("Save State Slot 8"),
+
+ _("Load State Last 1"),
+ _("Load State Last 2"),
+ _("Load State Last 3"),
+ _("Load State Last 4"),
+ _("Load State Last 5"),
+ _("Load State Last 6"),
+ _("Load State Last 7"),
+ _("Load State Last 8"),
+
+ _("Save Oldest State"),
+ _("Undo Load State"),
+ _("Undo Save State")
};
const int page_breaks[3] = {HK_OPEN, HK_LOAD_STATE_SLOT_1, NUM_HOTKEYS};
diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp
index 3b2a79748d..efd84521f8 100644
--- a/Source/Core/DolphinWX/Src/ISOProperties.cpp
+++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp
@@ -818,14 +818,24 @@ void CISOProperties::OnExtractDir(wxCommandEvent& event)
void CISOProperties::OnExtractDataFromHeader(wxCommandEvent& event)
{
std::vector fst;
- DiscIO::IFileSystem *FS = 0;
+ DiscIO::IFileSystem *FS = NULL;
wxString Path = wxDirSelector(_("Choose the folder to extract to"));
if (Path.empty())
return;
if (DiscIO::IsVolumeWiiDisc(OpenISO))
- FS = WiiDisc.at(1).FileSystem;
+ if(WiiDisc.size() > 0)
+ {
+ // Get the filesystem of the LAST partition
+ FS = WiiDisc.at(WiiDisc.size() - 1).FileSystem;
+ }
+ else
+ {
+ PanicAlertT("No partitions found for: %s!",
+ WxStrToStr(Path).c_str());
+ return;
+ }
else
FS = pFileSystem;
diff --git a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp
index cd17c4c682..ef4ae8d29b 100644
--- a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp
+++ b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp
@@ -5,6 +5,7 @@
#include "InputConfigDiag.h"
#include "UDPConfigDiag.h"
#include "WxUtils.h"
+#include "HW/Wiimote.h"
void GamepadPage::ConfigUDPWii(wxCommandEvent &event)
{
@@ -947,7 +948,7 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin
, m_plugin(plugin)
{
m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT);
- for (unsigned int i = 0; i < plugin.controllers.size(); ++i)
+ for (unsigned int i = 0; i < std::min(plugin.controllers.size(), (size_t)MAX_WIIMOTES); ++i)
{
GamepadPage* gp = new GamepadPage(m_pad_notebook, m_plugin, i, this);
m_padpages.push_back(gp);
diff --git a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp
index 9561295cb3..74015bd274 100644
--- a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp
+++ b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp
@@ -89,13 +89,53 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
dc.DrawRectangle( 0, 31 - z*31, 64, 2);
}
- // circle for visual aid for diagonal adjustment
+ // octagon for visual aid for diagonal adjustment
dc.SetPen(*wxLIGHT_GREY_PEN);
dc.SetBrush(*wxWHITE_BRUSH);
if ( GROUP_TYPE_STICK == (*g)->control_group->type )
{
- dc.SetBrush(*wxTRANSPARENT_BRUSH);
- dc.DrawCircle( 32, 32, 32);
+ // outline and fill colors
+ wxBrush LightGrayBrush(_T("#dddddd"));
+ wxPen LightGrayPen(_T("#bfbfbf"));
+ dc.SetBrush(LightGrayBrush);
+ dc.SetPen(LightGrayPen);
+
+ // polygon offset
+ float max
+ , diagonal
+ , box = 64
+ , d_of = box / 256.0
+ , x_of = box / 2.0;
+
+ if ((*g)->control_group->name == "Main Stick")
+ {
+ max = (87.0 / 127.0) * 100;
+ diagonal = (55.0 / 127.0) * 100.0;
+ }
+ else if ((*g)->control_group->name == "C-Stick")
+ {
+ max = (74.0 / 127.0) * 100;
+ diagonal = (46.0 / 127.0) * 100;
+ }
+ else
+ {
+ max = (82.0 / 127.0) * 100;
+ diagonal = (58.0 / 127.0) * 100;
+ }
+
+ // polygon corners
+ wxPoint Points[8];
+ Points[0].x = (int)(0.0 * d_of + x_of); Points[0].y = (int)(max * d_of + x_of);
+ Points[1].x = (int)(diagonal * d_of + x_of); Points[1].y = (int)(diagonal * d_of + x_of);
+ Points[2].x = (int)(max * d_of + x_of); Points[2].y = (int)(0.0 * d_of + x_of);
+ Points[3].x = (int)(diagonal * d_of + x_of); Points[3].y = (int)(-diagonal * d_of + x_of);
+ Points[4].x = (int)(0.0 * d_of + x_of); Points[4].y = (int)(-max * d_of + x_of);
+ Points[5].x = (int)(-diagonal * d_of + x_of); Points[5].y = (int)(-diagonal * d_of + x_of);
+ Points[6].x = (int)(-max * d_of + x_of); Points[6].y = (int)(0.0 * d_of + x_of);
+ Points[7].x = (int)(-diagonal * d_of + x_of); Points[7].y = (int)(diagonal * d_of + x_of);
+
+ // draw polygon
+ dc.DrawPolygon(8, Points);
}
else
{
@@ -106,7 +146,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
{
// deadzone circle
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
- dc.DrawCircle( 32, 32, ((*g)->control_group)->settings[0]->value * 32 );
+ dc.DrawCircle( 32, 32, ((*g)->control_group)->settings[SETTING_DEADZONE]->value * 32 );
}
// raw dot
diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp
index 4d623d5d0b..f1297e8026 100644
--- a/Source/Core/DolphinWX/Src/MainAndroid.cpp
+++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp
@@ -113,7 +113,7 @@ void Host_SysMessage(const char *fmt, ...)
char msg[512];
va_start(list, fmt);
- vsprintf(msg, fmt, list);
+ vsnprintf(msg, 512, fmt, list);
va_end(list);
size_t len = strlen(msg);
diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp
index 8ad34bed08..5a7d11f96e 100644
--- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp
+++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp
@@ -87,6 +87,7 @@ wxString aa_desc = wxTRANSLATE("Reduces the amount of aliasing caused by rasteri
wxString scaled_efb_copy_desc = wxTRANSLATE("Greatly increases quality of textures generated using render to texture effects.\nRaising the internal resolution will improve the effect of this setting.\nSlightly decreases performance and possibly causes issues (although unlikely).\n\nIf unsure, leave this checked.");
wxString pixel_lighting_desc = wxTRANSLATE("Calculate lighting of 3D graphics per-pixel rather than per vertex.\nDecreases emulation speed by some percent (depending on your GPU).\nThis usually is a safe enhancement, but might cause issues sometimes.\n\nIf unsure, leave this unchecked.");
wxString hacked_buffer_upload_desc = wxTRANSLATE("Use a hacked upload strategy to stream vertices.\nThis usually speed up, but is forbidden by OpenGL specification and may causes heavy glitches.\n\nIf unsure, leave this unchecked.");
+wxString fast_depth_calc_desc = wxTRANSLATE("Use a less accurate algorithm to calculate depth values.\nCauses issues in a few games but might give a decent speedup.\n\nIf unsure, leave this checked.");
wxString force_filtering_desc = wxTRANSLATE("Force texture filtering even if the emulated game explicitly disabled it.\nImproves texture quality slightly but causes glitches in some games.\n\nIf unsure, leave this unchecked.");
wxString _3d_vision_desc = wxTRANSLATE("Enable 3D effects via stereoscopy using Nvidia 3D Vision technology if it's supported by your GPU.\nPossibly causes issues.\nRequires fullscreen to work.\n\nIf unsure, leave this unchecked.");
wxString internal_res_desc = wxTRANSLATE("Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain games.\n\"Multiple of 640x528\" is a bit slower than \"Window Size\" but yields less issues. Generally speaking, the lower the internal resolution is, the better your performance will be.\n\nIf unsure, select 640x528.");
@@ -130,6 +131,7 @@ wxString shader_errors_desc = wxTRANSLATE("Usually if shader compilation fails,
wxArrayString GetListOfResolutions()
{
wxArrayString retlist;
+ retlist.Add("Auto");
#ifdef _WIN32
DWORD iModeNum = 0;
DEVMODE dmi;
@@ -496,15 +498,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
// - other hacks
{
wxGridSizer* const szr_other = new wxGridSizer(2, 5, 5);
- SettingCheckBox* hacked_buffer_upload_cb;
szr_other->Add(CreateCheckBox(page_hacks, _("Cache Display Lists"), wxGetTranslation(dlc_desc), vconfig.bDlistCachingEnable));
szr_other->Add(CreateCheckBox(page_hacks, _("Disable Destination Alpha"), wxGetTranslation(disable_dstalpha_desc), vconfig.bDstAlphaPass));
szr_other->Add(CreateCheckBox(page_hacks, _("OpenCL Texture Decoder"), wxGetTranslation(opencl_desc), vconfig.bEnableOpenCL));
szr_other->Add(CreateCheckBox(page_hacks, _("OpenMP Texture Decoder"), wxGetTranslation(omp_desc), vconfig.bOMPDecoder));
- szr_other->Add(hacked_buffer_upload_cb = CreateCheckBox(page_hacks, _("Hacked Buffer Upload"), wxGetTranslation(hacked_buffer_upload_desc), vconfig.bHackedBufferUpload));
-
- if (Core::GetState() != Core::CORE_UNINITIALIZED)
- hacked_buffer_upload_cb->Disable();
+ szr_other->Add(CreateCheckBox(page_hacks, _("Fast Depth Calculation"), wxGetTranslation(fast_depth_calc_desc), vconfig.bFastDepthCalc));
+ szr_other->Add(hacked_buffer_upload = CreateCheckBox(page_hacks, _("Hacked Buffer Upload"), wxGetTranslation(hacked_buffer_upload_desc), vconfig.bHackedBufferUpload));
wxStaticBoxSizer* const group_other = new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("Other"));
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.h b/Source/Core/DolphinWX/Src/VideoConfigDiag.h
index 90a42c34a1..563f5076d6 100644
--- a/Source/Core/DolphinWX/Src/VideoConfigDiag.h
+++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.h
@@ -8,6 +8,7 @@
#include "ConfigManager.h"
#include "VideoConfig.h"
+#include "Core.h"
#include
#include
@@ -165,6 +166,10 @@ protected:
// XFB
virtual_xfb->Enable(vconfig.bUseXFB);
real_xfb->Enable(vconfig.bUseXFB);
+
+ // OGL Hacked buffer
+ hacked_buffer_upload->Enable(Core::GetState() == Core::CORE_UNINITIALIZED && vconfig.backend_info.APIType == API_OPENGL);
+ hacked_buffer_upload->Show(vconfig.backend_info.APIType == API_OPENGL);
ev.Skip();
}
@@ -194,6 +199,7 @@ protected:
SettingRadioButton* efbcopy_ram;
SettingCheckBox* cache_efb_copies;
SettingCheckBox* emulate_efb_format_changes;
+ SettingCheckBox* hacked_buffer_upload;
SettingRadioButton* virtual_xfb;
SettingRadioButton* real_xfb;
diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp
index f039fe4938..be29f11015 100644
--- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp
+++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp
@@ -15,7 +15,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wxStaticText* wiimote_label[4];
wxChoice* wiimote_source_ch[4];
- for (unsigned int i = 0; i < 4; ++i)
+ for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
wxString str;
str.Printf(_("Wiimote %i"), i + 1);
@@ -54,8 +54,25 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wiimote_sizer->Add(wiimote_configure_bt[i]);
}
wiimote_group->Add(wiimote_sizer, 1, wxEXPAND, 5 );
+
+
+ // "BalanceBoard" layout
+ wxStaticBoxSizer* const bb_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Balance Board"));
+ wxFlexGridSizer* const bb_sizer = new wxFlexGridSizer(1, 5, 5);
+ int source_ctrl_id = wxWindow::NewControlId();
+ m_wiimote_index_from_ctrl_id.insert(std::pair(source_ctrl_id, WIIMOTE_BALANCE_BOARD));
+ const wxString src_choices[] = { _("None"), _("Real Balance Board") };
+ wxChoice* bb_source = new wxChoice(this, source_ctrl_id, wxDefaultPosition, wxDefaultSize, sizeof(src_choices)/sizeof(*src_choices), src_choices);
+ bb_source->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &WiimoteConfigDiag::SelectSource, this);
+
+ m_orig_wiimote_sources[WIIMOTE_BALANCE_BOARD] = g_wiimote_sources[WIIMOTE_BALANCE_BOARD];
+ bb_source->Select(m_orig_wiimote_sources[WIIMOTE_BALANCE_BOARD] ? 1 : 0);
+
+ bb_sizer->Add(bb_source, 0, wxALIGN_CENTER_VERTICAL);
+
+ bb_group->Add(bb_sizer, 1, wxEXPAND, 5 );
-
+
// "Real wiimotes" controls
wxButton* const refresh_btn = new wxButton(this, -1, _("Refresh"), wxDefaultPosition);
refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this);
@@ -166,6 +183,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
// Dialog layout
main_sizer->Add(wiimote_group, 0, wxEXPAND | wxALL, 5);
+ main_sizer->Add(bb_group, 0, wxEXPAND | wxALL, 5);
main_sizer->Add(real_wiimotes_group, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
main_sizer->Add(general_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
@@ -196,17 +214,23 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event)
// Revert if the dialog is canceled.
int index = m_wiimote_index_from_ctrl_id[event.GetId()];
- WiimoteReal::ChangeWiimoteSource(index, event.GetInt());
-
- if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID)
- wiimote_configure_bt[index]->Disable();
+ if(index != WIIMOTE_BALANCE_BOARD)
+ {
+ WiimoteReal::ChangeWiimoteSource(index, event.GetInt());
+ if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID)
+ wiimote_configure_bt[index]->Disable();
+ else
+ wiimote_configure_bt[index]->Enable();
+ }
else
- wiimote_configure_bt[index]->Enable();
+ {
+ WiimoteReal::ChangeWiimoteSource(index, event.GetInt() ? WIIMOTE_SRC_REAL : WIIMOTE_SRC_NONE);
+ }
}
void WiimoteConfigDiag::RevertSource()
{
- for (int i = 0; i < 4; ++i)
+ for (int i = 0; i < MAX_BBMOTES; ++i)
g_wiimote_sources[i] = m_orig_wiimote_sources[i];
}
@@ -225,6 +249,10 @@ void WiimoteConfigDiag::Save(wxCommandEvent& event)
sec.Set("Source", (int)g_wiimote_sources[i]);
}
+
+ std::string secname("BalanceBoard");
+ IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str());
+ sec.Set("Source", (int)g_wiimote_sources[WIIMOTE_BALANCE_BOARD]);
inifile.Save(ini_filename);
diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h
index 4c33661ca2..dac963d9f3 100644
--- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h
+++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h
@@ -76,9 +76,9 @@ private:
wxNotebook* m_pad_notebook;
std::map m_wiimote_index_from_ctrl_id;
- unsigned int m_orig_wiimote_sources[4];
+ unsigned int m_orig_wiimote_sources[MAX_BBMOTES];
- wxButton* wiimote_configure_bt[4];
+ wxButton* wiimote_configure_bt[MAX_WIIMOTES];
std::map m_wiimote_index_from_conf_bt_id;
};
diff --git a/Source/Core/DolphinWX/Src/X11Utils.cpp b/Source/Core/DolphinWX/Src/X11Utils.cpp
index 6c4282cceb..9be4d23fbf 100644
--- a/Source/Core/DolphinWX/Src/X11Utils.cpp
+++ b/Source/Core/DolphinWX/Src/X11Utils.cpp
@@ -200,6 +200,9 @@ XRRConfiguration::~XRRConfiguration()
void XRRConfiguration::Update()
{
+ if(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution == "Auto")
+ return;
+
if (!bValid)
return;
diff --git a/Source/Core/InputCommon/Src/Android/ButtonManager.cpp b/Source/Core/InputCommon/Src/Android/ButtonManager.cpp
index 947f7b0081..9ae996732d 100644
--- a/Source/Core/InputCommon/Src/Android/ButtonManager.cpp
+++ b/Source/Core/InputCommon/Src/Android/ButtonManager.cpp
@@ -37,9 +37,6 @@ namespace ButtonManager
void Init()
{
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
// Initialize our buttons
m_buttons.push_back(new Button("ButtonA.png", BUTTON_A, m_coords[0]));
m_buttons.push_back(new Button("ButtonB.png", BUTTON_B, m_coords[1]));
@@ -83,8 +80,13 @@ namespace ButtonManager
void DrawButtons()
{
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
for(auto it = m_buttons.begin(); it != m_buttons.end(); ++it)
DrawButton((*it)->GetTexture(), (*it)->GetCoords());
+
+ glDisable(GL_BLEND);
}
}
diff --git a/Source/Core/InputCommon/Src/ControllerEmu.cpp b/Source/Core/InputCommon/Src/ControllerEmu.cpp
index b7eee1a143..328fcb8c2f 100644
--- a/Source/Core/InputCommon/Src/ControllerEmu.cpp
+++ b/Source/Core/InputCommon/Src/ControllerEmu.cpp
@@ -226,6 +226,7 @@ ControllerEmu::AnalogStick::AnalogStick(const char* const _name) : ControlGroup(
controls.push_back(new Input(_trans("Modifier")));
+ settings.push_back(new Setting(_trans("Radius"), 0.7f, 0, 100));
settings.push_back(new Setting(_trans("Dead Zone"), 0, 0, 50));
settings.push_back(new Setting(_trans("Square Stick"), 0));
diff --git a/Source/Core/InputCommon/Src/ControllerEmu.h b/Source/Core/InputCommon/Src/ControllerEmu.h
index 33057434cd..cf87f2562e 100644
--- a/Source/Core/InputCommon/Src/ControllerEmu.h
+++ b/Source/Core/InputCommon/Src/ControllerEmu.h
@@ -35,6 +35,13 @@ enum
GROUP_TYPE_SLIDER,
};
+enum
+{
+ SETTING_RADIUS,
+ SETTING_DEADZONE,
+ SETTING_SQUARE,
+};
+
const char * const named_directions[] =
{
"Up",
@@ -126,8 +133,9 @@ public:
ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
- ControlState deadzone = settings[0]->value;
- ControlState square = settings[1]->value;
+ ControlState radius = settings[SETTING_RADIUS]->value;
+ ControlState deadzone = settings[SETTING_DEADZONE]->value;
+ ControlState square = settings[SETTING_SQUARE]->value;
ControlState m = controls[4]->control_ref->State();
// modifier code
@@ -138,11 +146,11 @@ public:
}
// deadzone / square stick code
- if (deadzone || square)
+ if (radius != 1 || deadzone || square)
{
// this section might be all wrong, but its working good enough, I think
- ControlState ang = atan2(yy, xx);
+ ControlState ang = atan2(yy, xx);
ControlState ang_sin = sin(ang);
ControlState ang_cos = cos(ang);
@@ -163,6 +171,9 @@ public:
ControlState amt = dist / stick_full;
dist -= ((square_full - 1) * amt * square);
+ // radius
+ dist *= radius;
+
yy = std::max(-1.0f, std::min(1.0f, ang_sin * dist));
xx = std::max(-1.0f, std::min(1.0f, ang_cos * dist));
}
diff --git a/Source/Core/InputCommon/Src/InputConfig.cpp b/Source/Core/InputCommon/Src/InputConfig.cpp
index 65529b0a3f..96fc6205db 100644
--- a/Source/Core/InputCommon/Src/InputConfig.cpp
+++ b/Source/Core/InputCommon/Src/InputConfig.cpp
@@ -4,6 +4,7 @@
#include "InputConfig.h"
#include "../../Core/Src/ConfigManager.h"
+#include "../../Core/Src/HW/Wiimote.h"
InputPlugin::~InputPlugin()
{
@@ -18,9 +19,9 @@ bool InputPlugin::LoadConfig(bool isGC)
{
IniFile inifile;
IniFile game_ini;
- bool useProfile[4] = {false, false, false, false};
- std::string num[4] = {"1", "2", "3", "4"};
- std::string profile[4];
+ bool useProfile[MAX_BBMOTES] = {false, false, false, false, false};
+ std::string num[MAX_BBMOTES] = {"1", "2", "3", "4", "BB"};
+ std::string profile[MAX_BBMOTES];
std::string path;
if (SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() != "00000000")
diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt
index 89b6828281..1bbc69a150 100644
--- a/Source/Core/VideoCommon/CMakeLists.txt
+++ b/Source/Core/VideoCommon/CMakeLists.txt
@@ -4,6 +4,7 @@ set(SRCS Src/BPFunctions.cpp
Src/CPMemory.cpp
Src/CommandProcessor.cpp
Src/Debugger.cpp
+ Src/DriverDetails.cpp
Src/Fifo.cpp
Src/FPSCounter.cpp
Src/FramebufferManagerBase.cpp
diff --git a/Source/Core/VideoCommon/Src/BPMemory.cpp b/Source/Core/VideoCommon/Src/BPMemory.cpp
index e917632e1f..77f2f6bab3 100644
--- a/Source/Core/VideoCommon/Src/BPMemory.cpp
+++ b/Source/Core/VideoCommon/Src/BPMemory.cpp
@@ -89,6 +89,19 @@ void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size
}
break;
+ case BPMEM_ZCOMPARE:
+ {
+ SetRegName(BPMEM_ZCOMPARE);
+ PE_CONTROL config; config.hex = cmddata;
+ const char* pixel_formats[] = { "RGB8_Z24", "RGBA6_Z24", "RGB565_Z16", "Z24", "Y8", "U8", "V8", "YUV420" };
+ const char* zformats[] = { "linear", "compressed (near)", "compressed (mid)", "compressed (far)", "inv linear", "compressed (inv near)", "compressed (inv mid)", "compressed (inv far)" };
+ snprintf(desc, desc_size, "EFB pixel format: %s\n"
+ "Depth format: %s\n"
+ "Early depth test: %s\n",
+ pixel_formats[config.pixel_format], zformats[config.zformat], no_yes[config.early_ztest]);
+ }
+ break;
+
case BPMEM_EFB_BR: // 0x4A
{
// TODO: Misleading name, should be BPMEM_EFB_WH instead
@@ -162,6 +175,21 @@ void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size
// TODO: Description
break;
+ case BPMEM_TX_SETIMAGE3: // 0x94
+ case BPMEM_TX_SETIMAGE3+1:
+ case BPMEM_TX_SETIMAGE3+2:
+ case BPMEM_TX_SETIMAGE3+3:
+ case BPMEM_TX_SETIMAGE3_4: // 0xB4
+ case BPMEM_TX_SETIMAGE3_4+1:
+ case BPMEM_TX_SETIMAGE3_4+2:
+ case BPMEM_TX_SETIMAGE3_4+3:
+ {
+ SetRegName(BPMEM_TX_SETIMAGE3);
+ TexImage3 teximg; teximg.hex = cmddata;
+ snprintf(desc, desc_size, "Source address (32 byte aligned): 0x%06X", teximg.image_base << 5);
+ }
+ break;
+
case BPMEM_TEV_COLOR_ENV: // 0xC0
case BPMEM_TEV_COLOR_ENV+2:
case BPMEM_TEV_COLOR_ENV+4:
diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp
new file mode 100644
index 0000000000..8d3c2d9cf7
--- /dev/null
+++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp
@@ -0,0 +1,69 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include