diff --git a/desmume/src/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj b/desmume/src/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj index 2b82cd952..9ad1d7f15 100644 --- a/desmume/src/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj +++ b/desmume/src/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj @@ -251,7 +251,6 @@ AB2F3C2015CF9C6000858373 /* cocoa_core.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104121346652500AF11D1 /* cocoa_core.mm */; }; AB2F3C2115CF9C6000858373 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB58F32C1364F44B0074C376 /* cocoa_file.mm */; }; AB2F3C2215CF9C6000858373 /* cocoa_firmware.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */; }; - AB2F3C2315CF9C6000858373 /* cocoa_hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB350B691478A5B3007165AC /* cocoa_hid.mm */; }; AB2F3C2415CF9C6000858373 /* cocoa_input.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104111346652500AF11D1 /* cocoa_input.mm */; }; AB2F3C2515CF9C6000858373 /* cocoa_mic.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD9A46413DB99B300777194 /* cocoa_mic.mm */; }; AB2F3C2615CF9C6000858373 /* cocoa_output.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB3E34C8134AF4500056477A /* cocoa_output.mm */; }; @@ -288,6 +287,10 @@ AB3ACC4614C24D5400D7D192 /* COPYING in Resources */ = {isa = PBXBuildFile; fileRef = AB3ACC3A14C24D5400D7D192 /* COPYING */; }; AB3ACC4714C24D5400D7D192 /* README in Resources */ = {isa = PBXBuildFile; fileRef = AB3ACC3B14C24D5400D7D192 /* README */; }; AB3ACC4914C24D5400D7D192 /* README.MAC in Resources */ = {isa = PBXBuildFile; fileRef = AB3ACC3D14C24D5400D7D192 /* README.MAC */; }; + AB5A795816D5A56000ED84B7 /* InputManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB5A795716D5A56000ED84B7 /* InputManager.mm */; }; + AB5A795916D5A56000ED84B7 /* InputManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB5A795716D5A56000ED84B7 /* InputManager.mm */; }; + AB5A795A16D5A56000ED84B7 /* InputManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB5A795716D5A56000ED84B7 /* InputManager.mm */; }; + AB5A795B16D5A56000ED84B7 /* InputManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB5A795716D5A56000ED84B7 /* InputManager.mm */; }; AB6A187C16C9951C00384EED /* EmuControllerDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6A187B16C9951C00384EED /* EmuControllerDelegate.mm */; }; AB6A187D16C9951C00384EED /* EmuControllerDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6A187B16C9951C00384EED /* EmuControllerDelegate.mm */; }; AB6A187E16C9951C00384EED /* EmuControllerDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6A187B16C9951C00384EED /* EmuControllerDelegate.mm */; }; @@ -410,7 +413,6 @@ AB711F6D1481C35F009011C8 /* videofilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB817A35143EE2DB00A7DFE9 /* videofilter.cpp */; }; AB711F6E1481C35F009011C8 /* cocoa_videofilter.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE5DFE4143FB1DA00835AD8 /* cocoa_videofilter.mm */; }; AB711F701481C35F009011C8 /* cocoa_cheat.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */; }; - AB711F721481C35F009011C8 /* cocoa_hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB350B691478A5B3007165AC /* cocoa_hid.mm */; }; AB711F741481C35F009011C8 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; AB711F751481C35F009011C8 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC570D0134431CE00E7B0B1 /* AudioUnit.framework */; }; AB711F761481C35F009011C8 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC570D4134431DA00E7B0B1 /* OpenGL.framework */; }; @@ -572,7 +574,6 @@ AB73AA0E1507C9F500A310C8 /* cocoa_core.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104121346652500AF11D1 /* cocoa_core.mm */; }; AB73AA0F1507C9F500A310C8 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB58F32C1364F44B0074C376 /* cocoa_file.mm */; }; AB73AA101507C9F500A310C8 /* cocoa_firmware.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */; }; - AB73AA111507C9F500A310C8 /* cocoa_hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB350B691478A5B3007165AC /* cocoa_hid.mm */; }; AB73AA121507C9F500A310C8 /* cocoa_input.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104111346652500AF11D1 /* cocoa_input.mm */; }; AB73AA131507C9F500A310C8 /* cocoa_mic.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD9A46413DB99B300777194 /* cocoa_mic.mm */; }; AB73AA141507C9F500A310C8 /* cocoa_output.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB3E34C8134AF4500056477A /* cocoa_output.mm */; }; @@ -764,7 +765,6 @@ ABAD101615ACE7A00000EC47 /* cocoa_core.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104121346652500AF11D1 /* cocoa_core.mm */; }; ABAD101715ACE7A00000EC47 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB58F32C1364F44B0074C376 /* cocoa_file.mm */; }; ABAD101815ACE7A00000EC47 /* cocoa_firmware.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */; }; - ABAD101915ACE7A00000EC47 /* cocoa_hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB350B691478A5B3007165AC /* cocoa_hid.mm */; }; ABAD101A15ACE7A00000EC47 /* cocoa_input.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104111346652500AF11D1 /* cocoa_input.mm */; }; ABAD101B15ACE7A00000EC47 /* cocoa_mic.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD9A46413DB99B300777194 /* cocoa_mic.mm */; }; ABAD101C15ACE7A00000EC47 /* cocoa_output.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB3E34C8134AF4500056477A /* cocoa_output.mm */; }; @@ -949,8 +949,6 @@ AB279D5716A4E6DE00ECC692 /* sse_optimized.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sse_optimized.cpp; sourceTree = ""; }; AB279D5816A4E6DE00ECC692 /* TDStretch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TDStretch.cpp; sourceTree = ""; }; AB2F3C4515CF9C6000858373 /* DeSmuME (PPC).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DeSmuME (PPC).app"; sourceTree = BUILT_PRODUCTS_DIR; }; - AB350B681478A5B3007165AC /* cocoa_hid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_hid.h; sourceTree = ""; }; - AB350B691478A5B3007165AC /* cocoa_hid.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_hid.mm; sourceTree = ""; }; AB350BA41478AC96007165AC /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; AB350D38147A1D8D007165AC /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = English; path = translations/English.lproj/HID_usage_strings.plist; sourceTree = ""; }; AB3ACB6614C2361100D7D192 /* appDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = appDelegate.h; sourceTree = ""; }; @@ -970,6 +968,8 @@ AB3E34C8134AF4500056477A /* cocoa_output.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_output.mm; sourceTree = ""; }; AB58F32B1364F44B0074C376 /* cocoa_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_file.h; sourceTree = ""; }; AB58F32C1364F44B0074C376 /* cocoa_file.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_file.mm; sourceTree = ""; }; + AB5A795616D5A56000ED84B7 /* InputManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputManager.h; sourceTree = ""; }; + AB5A795716D5A56000ED84B7 /* InputManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InputManager.mm; sourceTree = ""; }; AB64987B13ECC73800EE7DD2 /* FileTypeInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = FileTypeInfo.plist; sourceTree = ""; }; AB6A187A16C9951C00384EED /* EmuControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmuControllerDelegate.h; sourceTree = ""; }; AB6A187B16C9951C00384EED /* EmuControllerDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EmuControllerDelegate.mm; sourceTree = ""; }; @@ -1371,7 +1371,6 @@ ABE7F53C13EE1C7900FD3A71 /* cocoa_firmware.h */, AB9971CE134EDA0800531BA7 /* cocoa_globals.h */, AB6A198116CAD66900384EED /* cocoa_GPU.h */, - AB350B681478A5B3007165AC /* cocoa_hid.h */, ABD103FF1346652500AF11D1 /* cocoa_input.h */, ABD9A46313DB99B300777194 /* cocoa_mic.h */, AB3E34C7134AF4500056477A /* cocoa_output.h */, @@ -1386,7 +1385,6 @@ AB58F32C1364F44B0074C376 /* cocoa_file.mm */, ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */, AB6A198216CAD66900384EED /* cocoa_GPU.mm */, - AB350B691478A5B3007165AC /* cocoa_hid.mm */, ABD104111346652500AF11D1 /* cocoa_input.mm */, ABD9A46413DB99B300777194 /* cocoa_mic.mm */, AB3E34C8134AF4500056477A /* cocoa_output.mm */, @@ -1492,6 +1490,7 @@ AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */, AB700DDC16CDE4C300FBD336 /* DisplayWindowController.h */, AB6A187A16C9951C00384EED /* EmuControllerDelegate.h */, + AB5A795616D5A56000ED84B7 /* InputManager.h */, AB3ACB6E14C2361100D7D192 /* inputPrefsView.h */, AB3ACB7014C2361100D7D192 /* preferencesWindowDelegate.h */, ABA0356E169127BB00817C69 /* troubleshootingWindowDelegate.h */, @@ -1499,6 +1498,7 @@ AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */, AB700DDD16CDE4C300FBD336 /* DisplayWindowController.mm */, AB6A187B16C9951C00384EED /* EmuControllerDelegate.mm */, + AB5A795716D5A56000ED84B7 /* InputManager.mm */, AB3ACB6F14C2361100D7D192 /* inputPrefsView.mm */, AB3ACB7114C2361100D7D192 /* preferencesWindowDelegate.mm */, ABA0356F169127C000817C69 /* troubleshootingWindowDelegate.mm */, @@ -2614,7 +2614,6 @@ AB2F3C2015CF9C6000858373 /* cocoa_core.mm in Sources */, AB2F3C2115CF9C6000858373 /* cocoa_file.mm in Sources */, AB2F3C2215CF9C6000858373 /* cocoa_firmware.mm in Sources */, - AB2F3C2315CF9C6000858373 /* cocoa_hid.mm in Sources */, AB2F3C2415CF9C6000858373 /* cocoa_input.mm in Sources */, AB2F3C2515CF9C6000858373 /* cocoa_mic.mm in Sources */, AB2F3C2615CF9C6000858373 /* cocoa_output.mm in Sources */, @@ -2650,6 +2649,7 @@ AB6A187C16C9951C00384EED /* EmuControllerDelegate.mm in Sources */, AB6A198316CAD66900384EED /* cocoa_GPU.mm in Sources */, AB700DDF16CDE4C300FBD336 /* DisplayWindowController.mm in Sources */, + AB5A795B16D5A56000ED84B7 /* InputManager.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2742,7 +2742,6 @@ AB711F471481C35F009011C8 /* cocoa_core.mm in Sources */, AB711F4E1481C35F009011C8 /* cocoa_file.mm in Sources */, AB711F601481C35F009011C8 /* cocoa_firmware.mm in Sources */, - AB711F721481C35F009011C8 /* cocoa_hid.mm in Sources */, AB711F461481C35F009011C8 /* cocoa_input.mm in Sources */, AB711F5E1481C35F009011C8 /* cocoa_mic.mm in Sources */, AB711F4C1481C35F009011C8 /* cocoa_output.mm in Sources */, @@ -2807,6 +2806,7 @@ AB6A187E16C9951C00384EED /* EmuControllerDelegate.mm in Sources */, AB6A198516CAD66900384EED /* cocoa_GPU.mm in Sources */, AB700DE116CDE4C300FBD336 /* DisplayWindowController.mm in Sources */, + AB5A795916D5A56000ED84B7 /* InputManager.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2898,7 +2898,6 @@ AB73AA0E1507C9F500A310C8 /* cocoa_core.mm in Sources */, AB73AA0F1507C9F500A310C8 /* cocoa_file.mm in Sources */, AB73AA101507C9F500A310C8 /* cocoa_firmware.mm in Sources */, - AB73AA111507C9F500A310C8 /* cocoa_hid.mm in Sources */, AB73AA121507C9F500A310C8 /* cocoa_input.mm in Sources */, AB73AA131507C9F500A310C8 /* cocoa_mic.mm in Sources */, AB73AA141507C9F500A310C8 /* cocoa_output.mm in Sources */, @@ -2964,6 +2963,7 @@ AB6A187F16C9951C00384EED /* EmuControllerDelegate.mm in Sources */, AB6A198616CAD66900384EED /* cocoa_GPU.mm in Sources */, AB700DDE16CDE4C300FBD336 /* DisplayWindowController.mm in Sources */, + AB5A795A16D5A56000ED84B7 /* InputManager.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3055,7 +3055,6 @@ ABAD101615ACE7A00000EC47 /* cocoa_core.mm in Sources */, ABAD101715ACE7A00000EC47 /* cocoa_file.mm in Sources */, ABAD101815ACE7A00000EC47 /* cocoa_firmware.mm in Sources */, - ABAD101915ACE7A00000EC47 /* cocoa_hid.mm in Sources */, ABAD101A15ACE7A00000EC47 /* cocoa_input.mm in Sources */, ABAD101B15ACE7A00000EC47 /* cocoa_mic.mm in Sources */, ABAD101C15ACE7A00000EC47 /* cocoa_output.mm in Sources */, @@ -3091,6 +3090,7 @@ AB6A187D16C9951C00384EED /* EmuControllerDelegate.mm in Sources */, AB6A198416CAD66900384EED /* cocoa_GPU.mm in Sources */, AB700DE016CDE4C300FBD336 /* DisplayWindowController.mm in Sources */, + AB5A795816D5A56000ED84B7 /* InputManager.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/desmume/src/cocoa/DeSmuME (XCode 4).xcodeproj/project.pbxproj b/desmume/src/cocoa/DeSmuME (XCode 4).xcodeproj/project.pbxproj index aedab7d32..425906647 100644 --- a/desmume/src/cocoa/DeSmuME (XCode 4).xcodeproj/project.pbxproj +++ b/desmume/src/cocoa/DeSmuME (XCode 4).xcodeproj/project.pbxproj @@ -67,7 +67,8 @@ AB23567416C2F6F400DA782E /* macosx_10_5_compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */; }; AB23567516C2FAD800DA782E /* OGLRender_3_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */; }; AB26D87C16B5253D00A2305C /* OGLRender_3_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */; }; - AB350B6A1478A5B3007165AC /* cocoa_hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB350B691478A5B3007165AC /* cocoa_hid.mm */; }; + AB29B33116D4BEBF000EF671 /* InputManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB29B33016D4BEBF000EF671 /* InputManager.mm */; }; + AB29B33216D4BEBF000EF671 /* InputManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB29B33016D4BEBF000EF671 /* InputManager.mm */; }; AB350BA51478AC96007165AC /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB350BA41478AC96007165AC /* IOKit.framework */; }; AB350D3B147A1D93007165AC /* HID_usage_strings.plist in Resources */ = {isa = PBXBuildFile; fileRef = AB350D3A147A1D93007165AC /* HID_usage_strings.plist */; }; AB3A655E16CC5421001F5D4A /* EmuControllerDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB3A655D16CC5421001F5D4A /* EmuControllerDelegate.mm */; }; @@ -349,7 +350,6 @@ AB796D4B15CDCBA200C59155 /* cocoa_core.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104121346652500AF11D1 /* cocoa_core.mm */; }; AB796D4C15CDCBA200C59155 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB58F32C1364F44B0074C376 /* cocoa_file.mm */; }; AB796D4D15CDCBA200C59155 /* cocoa_firmware.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */; }; - AB796D4E15CDCBA200C59155 /* cocoa_hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB350B691478A5B3007165AC /* cocoa_hid.mm */; }; AB796D4F15CDCBA200C59155 /* cocoa_input.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104111346652500AF11D1 /* cocoa_input.mm */; }; AB796D5015CDCBA200C59155 /* cocoa_mic.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD9A46413DB99B300777194 /* cocoa_mic.mm */; }; AB796D5115CDCBA200C59155 /* cocoa_output.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB3E34C8134AF4500056477A /* cocoa_output.mm */; }; @@ -680,8 +680,8 @@ AB1B9E611501A78000464647 /* coreaudiosound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreaudiosound.h; sourceTree = SOURCE_ROOT; }; AB1B9E621501A78000464647 /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ringbuffer.h; sourceTree = SOURCE_ROOT; }; AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macosx_10_5_compat.cpp; sourceTree = ""; }; - AB350B681478A5B3007165AC /* cocoa_hid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_hid.h; sourceTree = ""; }; - AB350B691478A5B3007165AC /* cocoa_hid.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_hid.mm; sourceTree = ""; }; + AB29B32F16D4BEBF000EF671 /* InputManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputManager.h; sourceTree = ""; }; + AB29B33016D4BEBF000EF671 /* InputManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InputManager.mm; sourceTree = ""; }; AB350BA41478AC96007165AC /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; AB350D38147A1D8D007165AC /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = English; path = translations/English.lproj/HID_usage_strings.plist; sourceTree = ""; }; AB3A655C16CC5416001F5D4A /* EmuControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmuControllerDelegate.h; sourceTree = ""; }; @@ -1115,7 +1115,6 @@ ABE7F53C13EE1C7900FD3A71 /* cocoa_firmware.h */, AB9971CE134EDA0800531BA7 /* cocoa_globals.h */, AB3A656416CC5442001F5D4A /* cocoa_GPU.h */, - AB350B681478A5B3007165AC /* cocoa_hid.h */, ABD103FF1346652500AF11D1 /* cocoa_input.h */, ABD9A46313DB99B300777194 /* cocoa_mic.h */, AB3E34C7134AF4500056477A /* cocoa_output.h */, @@ -1130,7 +1129,6 @@ AB58F32C1364F44B0074C376 /* cocoa_file.mm */, ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */, AB3A656016CC5438001F5D4A /* cocoa_GPU.mm */, - AB350B691478A5B3007165AC /* cocoa_hid.mm */, ABD104111346652500AF11D1 /* cocoa_input.mm */, ABD9A46413DB99B300777194 /* cocoa_mic.mm */, AB3E34C8134AF4500056477A /* cocoa_output.mm */, @@ -1236,6 +1234,7 @@ AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */, AB8967D716D2ED0700F826F1 /* DisplayWindowController.h */, AB3A655C16CC5416001F5D4A /* EmuControllerDelegate.h */, + AB29B32F16D4BEBF000EF671 /* InputManager.h */, AB3ACB6E14C2361100D7D192 /* inputPrefsView.h */, AB3ACB7014C2361100D7D192 /* preferencesWindowDelegate.h */, ABF2B9F81690412A000FF7C0 /* troubleshootingWindowDelegate.h */, @@ -1243,6 +1242,7 @@ AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */, AB8967D816D2ED0700F826F1 /* DisplayWindowController.mm */, AB3A655D16CC5421001F5D4A /* EmuControllerDelegate.mm */, + AB29B33016D4BEBF000EF671 /* InputManager.mm */, AB3ACB6F14C2361100D7D192 /* inputPrefsView.mm */, AB3ACB7114C2361100D7D192 /* preferencesWindowDelegate.mm */, ABF2B9FA16904133000FF7C0 /* troubleshootingWindowDelegate.mm */, @@ -2182,7 +2182,6 @@ ABD1041D1346652500AF11D1 /* cocoa_core.mm in Sources */, AB58F32D1364F44B0074C376 /* cocoa_file.mm in Sources */, ABE7F53E13EE1C7900FD3A71 /* cocoa_firmware.mm in Sources */, - AB350B6A1478A5B3007165AC /* cocoa_hid.mm in Sources */, ABD1041C1346652500AF11D1 /* cocoa_input.mm in Sources */, ABD9A46513DB99B300777194 /* cocoa_mic.mm in Sources */, AB3E34C9134AF4500056477A /* cocoa_output.mm in Sources */, @@ -2239,6 +2238,7 @@ AB3A655F16CC5421001F5D4A /* EmuControllerDelegate.mm in Sources */, AB3A656216CC5438001F5D4A /* cocoa_GPU.mm in Sources */, AB8967DA16D2ED0700F826F1 /* DisplayWindowController.mm in Sources */, + AB29B33216D4BEBF000EF671 /* InputManager.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2341,7 +2341,6 @@ AB796D4B15CDCBA200C59155 /* cocoa_core.mm in Sources */, AB796D4C15CDCBA200C59155 /* cocoa_file.mm in Sources */, AB796D4D15CDCBA200C59155 /* cocoa_firmware.mm in Sources */, - AB796D4E15CDCBA200C59155 /* cocoa_hid.mm in Sources */, AB796D4F15CDCBA200C59155 /* cocoa_input.mm in Sources */, AB796D5015CDCBA200C59155 /* cocoa_mic.mm in Sources */, AB796D5115CDCBA200C59155 /* cocoa_output.mm in Sources */, @@ -2396,6 +2395,7 @@ AB3A655E16CC5421001F5D4A /* EmuControllerDelegate.mm in Sources */, AB3A656116CC5438001F5D4A /* cocoa_GPU.mm in Sources */, AB8967D916D2ED0700F826F1 /* DisplayWindowController.mm in Sources */, + AB29B33116D4BEBF000EF671 /* InputManager.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/desmume/src/cocoa/DefaultKeyMappings.plist b/desmume/src/cocoa/DefaultKeyMappings.plist index ccf88347e..14be6eb99 100644 --- a/desmume/src/cocoa/DefaultKeyMappings.plist +++ b/desmume/src/cocoa/DefaultKeyMappings.plist @@ -229,10 +229,6 @@ - floatValue 0.5 - selector - toggleHoldSpeedHalf: - paramType - floatValue Speed Double @@ -248,10 +244,6 @@ = floatValue 2 - selector - toggleHoldSpeedDouble: - paramType - floatValue HUD @@ -265,8 +257,6 @@ 4 elementName H - selector - toggleHoldHUD Execute @@ -280,8 +270,6 @@ 117 elementName Forward Delete - selector - execute Pause @@ -295,8 +283,6 @@ 119 elementName End - selector - pause Reset @@ -310,8 +296,6 @@ 121 elementName Page Down - selector - reset Mute @@ -325,8 +309,6 @@ 71 elementName Numpad Clear - selector - mute diff --git a/desmume/src/cocoa/cocoa_core.mm b/desmume/src/cocoa/cocoa_core.mm index efdfda99f..b8c72de8e 100644 --- a/desmume/src/cocoa/cocoa_core.mm +++ b/desmume/src/cocoa/cocoa_core.mm @@ -710,7 +710,7 @@ static void* RunCoreThread(void *arg) // Get the user's input, execute a single emulation frame, and generate // the frame output. - [(CocoaDSController *)param->cdsController update]; + [(CocoaDSController *)param->cdsController flush]; NDS_beginProcessingInput(); // Shouldn't need to do any special processing steps in between. diff --git a/desmume/src/cocoa/cocoa_hid.h b/desmume/src/cocoa/cocoa_hid.h deleted file mode 100644 index 66cf52022..000000000 --- a/desmume/src/cocoa/cocoa_hid.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright (C) 2011 Roger Manuel - Copyright (C) 2012 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . -*/ - -#import -#include -#include - - -@interface CocoaHIDDevice : NSObject -{ - IOHIDDeviceRef hidDeviceRef; - IOHIDQueueRef hidQueueRef; - NSRunLoop *runLoop; - OSSpinLock spinlockRunLoop; -} - -@property (readonly) IOHIDDeviceRef hidDeviceRef; -@property (retain) NSRunLoop *runLoop; - -- (id) initWithDevice:(IOHIDDeviceRef)theDevice; - -- (void) start; -- (void) stop; - -- (NSString *) manufacturerName; -- (NSString *) productName; -- (NSString *) serialNumber; - -+ (NSString *) manufacturerNameFromHIDDevice:(CocoaHIDDevice *)hidDevice; -+ (NSString *) productNameFromHIDDevice:(CocoaHIDDevice *)hidDevice; -+ (NSString *) serialNumberFromHIDDevice:(CocoaHIDDevice *)hidDevice; - -+ (NSMutableArray *) inputArrayFromHIDValue:(IOHIDValueRef)hidValueRef; -+ (NSDictionary *) inputAttributesOfHIDValue:(IOHIDValueRef)hidValueRef altElementCode:(NSString *)altElementCode altElementName:(NSString *)altElementName inputState:(NSNumber *)altOnState; -+ (NSMutableArray *) inputArrayFromHatSwitchValue:(IOHIDValueRef)hidValueRef useEightDirection:(BOOL)useEightDirection; -+ (BOOL) onStateFromHIDValue:(IOHIDValueRef)hidValueRef; - -@end - - -@interface CocoaHIDManager : NSObject -{ - IOHIDManagerRef hidManagerRef; - NSRunLoop *runLoop; - NSMutableSet *deviceList; - OSSpinLock spinlockRunLoop; -} - -@property (readonly) IOHIDManagerRef hidManagerRef; -@property (readonly) NSMutableSet *deviceList; -@property (retain) NSRunLoop *runLoop; - -@end - -void HandleDeviceMatchingCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef); -void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef); -void HandleQueueValueAvailableCallback(void *inContext, IOReturn inResult, void *inSender); diff --git a/desmume/src/cocoa/cocoa_hid.mm b/desmume/src/cocoa/cocoa_hid.mm deleted file mode 100644 index 5da830fce..000000000 --- a/desmume/src/cocoa/cocoa_hid.mm +++ /dev/null @@ -1,888 +0,0 @@ -/* - Copyright (C) 2011 Roger Manuel - Copyright (C) 2012 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . -*/ - -#import "cocoa_hid.h" -#import "cocoa_util.h" - -/* - Get the symbols for UpdateSystemActivity(). - - For some reason, in Mac OS v10.5 and earlier, UpdateSystemActivity() is not - defined for 64-bit, even though it does work on 64-bit systems. So we're going - to copy the symbols from OSServices/Power.h so that we can use them. This - solution is better than making an absolute path to the Power.h file, since - we can't assume that the header file will always be in the same location. - - Note that this isn't a problem on 32-bit, or if the target SDK is Mac OS v10.6 - or later. - */ - -#if !__LP64__ || MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 - -#include - -#else - -#ifdef __cplusplus -extern "C" -{ -#endif - - extern OSErr UpdateSystemActivity(UInt8 activity); - - enum - { - OverallAct = 0, - UsrActivity = 1, - NetActivity = 2, - HDActivity = 3, - IdleActivity = 4 - }; - -#ifdef __cplusplus -} -#endif - -#endif // !__LP64__ || MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 - -@implementation CocoaHIDDevice - -@synthesize hidDeviceRef; -@dynamic runLoop; - -static NSDictionary *hidUsageTable = nil; - -- (id)init -{ - return [self initWithDevice:nil]; -} - -- (id) initWithDevice:(IOHIDDeviceRef)theDevice -{ - self = [super init]; - if(self == nil) - { - return self; - } - - if (hidUsageTable == nil) - { - hidUsageTable = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HID_usage_strings" ofType:@"plist"]]; - } - - hidDeviceRef = theDevice; - - hidQueueRef = IOHIDQueueCreate(kCFAllocatorDefault, hidDeviceRef, 10, kIOHIDOptionsTypeNone); - if (hidQueueRef == NULL) - { - [self release]; - return nil; - } - - CFArrayRef elementArray = IOHIDDeviceCopyMatchingElements(hidDeviceRef, NULL, kIOHIDOptionsTypeNone); - NSEnumerator *enumerator = [(NSArray *)elementArray objectEnumerator]; - IOHIDElementRef hidElement = NULL; - - while ((hidElement = (IOHIDElementRef)[enumerator nextObject])) - { - IOHIDQueueAddElement(hidQueueRef, hidElement); - } - - CFRelease(elementArray); - - spinlockRunLoop = OS_SPINLOCK_INIT; - [self setRunLoop:[NSRunLoop currentRunLoop]]; - - return self; -} - -- (void)dealloc -{ - [self stop]; - - self.runLoop = nil; - - if (hidQueueRef != NULL) - { - CFRelease(hidQueueRef); - hidQueueRef = NULL; - } - - [super dealloc]; -} - -- (void) setRunLoop:(NSRunLoop *)theRunLoop -{ - OSSpinLockLock(&spinlockRunLoop); - - if (theRunLoop == runLoop) - { - OSSpinLockUnlock(&spinlockRunLoop); - return; - } - - if (theRunLoop == nil) - { - IOHIDQueueRegisterValueAvailableCallback(hidQueueRef, NULL, NULL); - IOHIDQueueUnscheduleFromRunLoop(hidQueueRef, [runLoop getCFRunLoop], kCFRunLoopDefaultMode); - } - else - { - [theRunLoop retain]; - IOHIDQueueScheduleWithRunLoop(hidQueueRef, [theRunLoop getCFRunLoop], kCFRunLoopDefaultMode); - IOHIDQueueRegisterValueAvailableCallback(hidQueueRef, HandleQueueValueAvailableCallback, self); - } - - [runLoop release]; - runLoop = theRunLoop; - - OSSpinLockUnlock(&spinlockRunLoop); -} - -- (NSRunLoop *) runLoop -{ - OSSpinLockLock(&spinlockRunLoop); - NSRunLoop *theRunLoop = runLoop; - OSSpinLockUnlock(&spinlockRunLoop); - - return theRunLoop; -} - -- (void) start -{ - IOHIDQueueStart(hidQueueRef); -} - -- (void) stop -{ - IOHIDQueueStop(hidQueueRef); -} - -- (NSString *) manufacturerName -{ - return [CocoaHIDDevice manufacturerNameFromHIDDevice:self]; -} - -- (NSString *) productName -{ - return [CocoaHIDDevice productNameFromHIDDevice:self]; -} - -- (NSString *) serialNumber -{ - return [CocoaHIDDevice serialNumberFromHIDDevice:self]; -} - -/******************************************************************************************** - inputAttributesOfHIDValue:altElementCode:altElementName:inputState: - - Parses an IOHIDValueRef to return an input attributes NSDictionary. - - Takes: - hidValueRef - The IOHIDValueRef to parse. - altElementCode - An NSString that overrides the default element code. - altElementName - An NSString that overrides the default element name. - altOnState - An NSNumber that overrides the default on state. - - Returns: - An input attributes NSDictionary. - - Details: - None. - ********************************************************************************************/ -+ (NSDictionary *) inputAttributesOfHIDValue:(IOHIDValueRef)hidValueRef altElementCode:(NSString *)altElementCode altElementName:(NSString *)altElementName inputState:(NSNumber *)altOnState -{ - if (hidValueRef == NULL) - { - return nil; - } - - IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef); - NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef); - NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef); - - NSString *elementCode = nil; - if (altElementCode == nil) - { - elementCode = [NSString stringWithFormat:@"0x%04lX/0x%04lX", (long)elementUsagePage, (long)elementUsage]; - } - else - { - elementCode = altElementCode; - } - - NSString *elementName = nil; - if (altElementName == nil) - { - - CFStringRef cfElementName = IOHIDElementGetName(hidElementRef); - if (cfElementName == nil) - { - if (elementUsagePage == kHIDPage_Button) - { - elementName = [NSString stringWithFormat:@"Button %li", (long)elementUsage]; - } - else if (elementUsagePage == kHIDPage_VendorDefinedStart) - { - elementName = [NSString stringWithFormat:@"VendorDefined %li", (long)elementUsage]; - } - else - { - NSDictionary *elementUsagePageDict = (NSDictionary *)[hidUsageTable valueForKey:[NSString stringWithFormat:@"0x%04lX", (long)elementUsagePage]]; - elementName = (NSString *)[elementUsagePageDict valueForKey:[NSString stringWithFormat:@"0x%04lX", (long)elementUsage]]; - } - } - else - { - elementName = [NSString stringWithString:(NSString *)cfElementName]; - } - } - else - { - elementName = altElementName; - } - - IOHIDDeviceRef hidDeviceRef = IOHIDElementGetDevice(hidElementRef); - - CFNumberRef cfVendorIDNumber = (CFNumberRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDVendorIDKey)); - CFNumberRef cfProductIDNumber = (CFNumberRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDProductIDKey)); - UInt32 vendorID = [(NSNumber *)cfVendorIDNumber integerValue]; - UInt32 productID = [(NSNumber *)cfProductIDNumber integerValue]; - - NSString *deviceCode = [NSString stringWithFormat:@"%d/%d/", vendorID, productID]; - CFStringRef cfDeviceCode = (CFStringRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDSerialNumberKey)); - if (cfDeviceCode == nil) - { - CFNumberRef cfLocationIDNumber = (CFNumberRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDLocationIDKey)); - UInt32 locationID = [(NSNumber *)cfLocationIDNumber integerValue]; - deviceCode = [deviceCode stringByAppendingFormat:@"0x%08X", locationID]; - } - else - { - deviceCode = [deviceCode stringByAppendingString:(NSString *)cfDeviceCode]; - } - - NSString *deviceName = nil; - CFStringRef cfDeviceName = (CFStringRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDProductKey)); - if (cfDeviceName == nil) - { - deviceName = deviceCode; - } - else - { - deviceName = [NSString stringWithString:(NSString *)cfDeviceName]; - } - - NSNumber *onState = nil; - if (altOnState == nil) - { - onState = [NSNumber numberWithBool:[CocoaHIDDevice onStateFromHIDValue:hidValueRef]]; - } - else - { - onState = altOnState; - } - - NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef); - - return [NSDictionary dictionaryWithObjectsAndKeys: - deviceCode, @"deviceCode", - deviceName, @"deviceName", - elementCode, @"elementCode", - elementName, @"elementName", - onState, @"on", - [NSNumber numberWithInteger:logicalValue], @"integerValue", - [NSNumber numberWithFloat:(float)logicalValue], @"floatValue", - nil]; -} - -+ (NSString *) manufacturerNameFromHIDDevice:(CocoaHIDDevice *)hidDevice -{ - return (NSString *)IOHIDDeviceGetProperty(hidDevice.hidDeviceRef, CFSTR(kIOHIDManufacturerKey)); -} - -+ (NSString *) productNameFromHIDDevice:(CocoaHIDDevice *)hidDevice -{ - return (NSString *)IOHIDDeviceGetProperty(hidDevice.hidDeviceRef, CFSTR(kIOHIDProductKey)); -} - -+ (NSString *) serialNumberFromHIDDevice:(CocoaHIDDevice *)hidDevice -{ - return (NSString *)IOHIDDeviceGetProperty(hidDevice.hidDeviceRef, CFSTR(kIOHIDSerialNumberKey)); -} - -+ (NSMutableArray *) inputArrayFromHIDValue:(IOHIDValueRef)hidValueRef -{ - NSMutableArray *inputAttributesList = nil; - - if (hidValueRef == NULL) - { - return inputAttributesList; - } - - IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef); - NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef); - NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef); - - // IOHIDValueGetIntegerValue() will crash if the value length is too large. - // Do a bounds check here to prevent crashing. This workaround makes the PS3 - // controller usable, since it returns a length of 39 on some elements. - if(IOHIDValueGetLength(hidValueRef) > 2) - { - return inputAttributesList; - } - - NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef); - NSInteger logicalMin = IOHIDElementGetLogicalMin(hidElementRef); - NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef); - - inputAttributesList = [NSMutableArray arrayWithCapacity:2]; - - if (logicalMin == 0 && logicalMax == 1) - { - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:nil altElementName:nil inputState:nil]]; - } - else - { - NSInteger lowerThreshold = ((logicalMax - logicalMin) / 3) + logicalMin; - NSInteger upperThreshold = (((logicalMax - logicalMin) * 2) / 3) + logicalMin; - NSNumber *onState = [NSNumber numberWithBool:YES]; - NSNumber *offState = [NSNumber numberWithBool:NO]; - NSString *elementCodeLowerThreshold = [NSString stringWithFormat:@"0x%04lX/0x%04lX/LowerThreshold", (long)elementUsagePage, (long)elementUsage]; - NSString *elementCodeUpperThreshold = [NSString stringWithFormat:@"0x%04lX/0x%04lX/UpperThreshold", (long)elementUsagePage, (long)elementUsage]; - - if (logicalValue <= lowerThreshold) - { - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeLowerThreshold altElementName:nil inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeUpperThreshold altElementName:nil inputState:offState]]; - } - else if (logicalValue >= upperThreshold) - { - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeLowerThreshold altElementName:nil inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeUpperThreshold altElementName:nil inputState:onState]]; - } - else - { - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeLowerThreshold altElementName:nil inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeUpperThreshold altElementName:nil inputState:offState]]; - } - } - - return inputAttributesList; -} - -+ (NSMutableArray *) inputArrayFromHatSwitchValue:(IOHIDValueRef)hidValueRef useEightDirection:(BOOL)useEightDirection -{ - NSMutableArray *inputAttributesList = nil; - - if (hidValueRef == NULL) - { - return inputAttributesList; - } - - IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef); - NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef); - NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef); - - if (elementUsage != kHIDUsage_GD_Hatswitch) - { - return inputAttributesList; - } - - inputAttributesList = [NSMutableArray arrayWithCapacity:8]; - NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef); - NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef); - - NSNumber *onState = [NSNumber numberWithBool:YES]; - NSNumber *offState = [NSNumber numberWithBool:NO]; - NSString *elementCodeFourWayUp = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-FourDirection", (long)elementUsagePage, (long)elementUsage, 0]; - NSString *elementCodeFourWayRight = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-FourDirection", (long)elementUsagePage, (long)elementUsage, 1]; - NSString *elementCodeFourWayDown = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-FourDirection", (long)elementUsagePage, (long)elementUsage, 2]; - NSString *elementCodeFourWayLeft = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-FourDirection", (long)elementUsagePage, (long)elementUsage, 3]; - NSString *elementCodeEightWayUp = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, 0]; - NSString *elementCodeEightWayUpRight = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, 1]; - NSString *elementCodeEightWayRight = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, 2]; - NSString *elementCodeEightWayDownRight = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, 3]; - NSString *elementCodeEightWayDown = [NSString stringWithFormat:@"0x%04lXX/0x%04lX/%d-EightDirection",(long) (long)elementUsagePage, (long)elementUsage, 4]; - NSString *elementCodeEightWayDownLeft = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, 5]; - NSString *elementCodeEightWayLeft = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, 6]; - NSString *elementCodeEightWayUpLeft = [NSString stringWithFormat:@"0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, 7]; - - if (logicalMax == 3) - { - switch (logicalValue) - { - case 0: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayUp altElementName:@"Hatswitch - Up" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - - case 1: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayRight altElementName:@"Hatswitch - Right" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - - case 2: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayDown altElementName:@"Hatswitch - Down" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - - case 3: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayLeft altElementName:@"Hatswitch - Left" inputState:onState]]; - break; - - default: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeFourWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - } - } - else if (logicalMax == 7) - { - if (useEightDirection) - { - switch (logicalValue) - { - case 0: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:offState]]; - break; - - case 1: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:offState]]; - break; - - case 2: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:offState]]; - break; - - case 3: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:offState]]; - break; - - case 4: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:offState]]; - break; - - case 5: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:offState]]; - break; - - case 6: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:offState]]; - break; - - case 7: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:onState]]; - break; - - default: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpRight altElementName:@"Hatswitch - Up/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownRight altElementName:@"Hatswitch - Down/Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDownLeft altElementName:@"Hatswitch - Down/Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUpLeft altElementName:@"Hatswitch - Up/Left" inputState:offState]]; - break; - } - } - else - { - switch (logicalValue) - { - case 0: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - - case 1: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - - case 2: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - - case 3: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - - case 4: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - - case 5: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:onState]]; - break; - - case 6: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:onState]]; - break; - - case 7: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:onState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:onState]]; - break; - - default: - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayUp altElementName:@"Hatswitch - Up" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayRight altElementName:@"Hatswitch - Right" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayDown altElementName:@"Hatswitch - Down" inputState:offState]]; - [inputAttributesList addObject:[CocoaHIDDevice inputAttributesOfHIDValue:hidValueRef altElementCode:elementCodeEightWayLeft altElementName:@"Hatswitch - Left" inputState:offState]]; - break; - } - } - } - - return inputAttributesList; -} - -+ (BOOL) onStateFromHIDValue:(IOHIDValueRef)hidValueRef -{ - BOOL onState = NO; - - if (hidValueRef == nil) - { - return onState; - } - - IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef); - NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef); - NSInteger logicalMin = IOHIDElementGetLogicalMin(hidElementRef); - NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef); - NSInteger lowerThreshold = ((logicalMax - logicalMin) / 4) + logicalMin; - NSInteger upperThreshold = (((logicalMax - logicalMin) * 3) / 4) + logicalMin; - - NSInteger elementType = IOHIDElementGetType(hidElementRef); - switch (elementType) - { - case kIOHIDElementTypeInput_Misc: - { - if (logicalMin == 0 && logicalMax == 1) - { - if (logicalValue == 1) - { - onState = YES; - } - } - else - { - if (logicalValue <= lowerThreshold || logicalValue >= upperThreshold) - { - onState = YES; - } - } - break; - } - - case kIOHIDElementTypeInput_Button: - { - if (logicalValue == 1) - { - onState = YES; - } - break; - } - - case kIOHIDElementTypeInput_Axis: - { - if (logicalMin == 0 && logicalMax == 1) - { - if (logicalValue == 1) - { - onState = YES; - } - } - else - { - if (logicalValue <= lowerThreshold || logicalValue >= upperThreshold) - { - onState = YES; - } - } - break; - } - - default: - break; - } - - return onState; -} - -@end - - -@implementation CocoaHIDManager - -@synthesize hidManagerRef; -@synthesize deviceList; -@dynamic runLoop; - -- (id)init -{ - self = [super init]; - if(self == nil) - { - return self; - } - - hidManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - if (hidManagerRef == NULL) - { - [self release]; - return nil; - } - - deviceList = [[NSMutableSet alloc] initWithCapacity:32]; - - CFMutableDictionaryRef cfJoystickMatcher = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(cfJoystickMatcher, CFSTR(kIOHIDDeviceUsagePageKey), (CFNumberRef)[NSNumber numberWithInteger:kHIDPage_GenericDesktop]); - CFDictionarySetValue(cfJoystickMatcher, CFSTR(kIOHIDDeviceUsageKey), (CFNumberRef)[NSNumber numberWithInteger:kHIDUsage_GD_Joystick]); - - CFMutableDictionaryRef cfGamepadMatcher = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(cfGamepadMatcher, CFSTR(kIOHIDDeviceUsagePageKey), (CFNumberRef)[NSNumber numberWithInteger:kHIDPage_GenericDesktop]); - CFDictionarySetValue(cfGamepadMatcher, CFSTR(kIOHIDDeviceUsageKey), (CFNumberRef)[NSNumber numberWithInteger:kHIDUsage_GD_GamePad]); - - NSArray *matcherArray = [[NSArray alloc] initWithObjects:(NSMutableDictionary *)cfJoystickMatcher, (NSMutableDictionary *)cfGamepadMatcher, nil]; - - IOHIDManagerSetDeviceMatchingMultiple(hidManagerRef, (CFArrayRef)matcherArray); - - [matcherArray release]; - CFRelease(cfJoystickMatcher); - CFRelease(cfGamepadMatcher); - - spinlockRunLoop = OS_SPINLOCK_INIT; - [self setRunLoop:[NSRunLoop currentRunLoop]]; - - IOReturn result = IOHIDManagerOpen(hidManagerRef, kIOHIDOptionsTypeNone); - if (result != kIOReturnSuccess) - { - [self release]; - return nil; - } - - return self; -} - -- (void)dealloc -{ - self.runLoop = nil; - [deviceList release]; - - if (hidManagerRef != NULL) - { - IOHIDManagerClose(hidManagerRef, 0); - CFRelease(hidManagerRef); - hidManagerRef = NULL; - } - - [super dealloc]; -} - -- (void) setRunLoop:(NSRunLoop *)theRunLoop -{ - OSSpinLockLock(&spinlockRunLoop); - - if (theRunLoop == runLoop) - { - OSSpinLockUnlock(&spinlockRunLoop); - return; - } - - if (theRunLoop == nil) - { - IOHIDManagerRegisterDeviceMatchingCallback(hidManagerRef, NULL, NULL); - IOHIDManagerRegisterDeviceRemovalCallback(hidManagerRef, NULL, NULL); - IOHIDManagerUnscheduleFromRunLoop(hidManagerRef, [runLoop getCFRunLoop], kCFRunLoopDefaultMode); - } - else - { - [theRunLoop retain]; - IOHIDManagerScheduleWithRunLoop(hidManagerRef, [theRunLoop getCFRunLoop], kCFRunLoopDefaultMode); - IOHIDManagerRegisterDeviceMatchingCallback(hidManagerRef, HandleDeviceMatchingCallback, self); - IOHIDManagerRegisterDeviceRemovalCallback(hidManagerRef, HandleDeviceRemovalCallback, self); - } - - [runLoop release]; - runLoop = theRunLoop; - - OSSpinLockUnlock(&spinlockRunLoop); -} - -- (NSRunLoop *) runLoop -{ - OSSpinLockLock(&spinlockRunLoop); - NSRunLoop *theRunLoop = runLoop; - OSSpinLockUnlock(&spinlockRunLoop); - - return theRunLoop; -} - -@end - -void HandleDeviceMatchingCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) -{ - CocoaHIDManager *hidManager = (CocoaHIDManager *)inContext; - CocoaHIDDevice *newDevice = [[[CocoaHIDDevice alloc] initWithDevice:inIOHIDDeviceRef] autorelease]; - [hidManager.deviceList addObject:newDevice]; - [newDevice start]; -} - -void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) -{ - CocoaHIDManager *hidManager = (CocoaHIDManager *)inContext; - - for (CocoaHIDDevice *hidDevice in hidManager.deviceList) - { - if (hidDevice.hidDeviceRef == inIOHIDDeviceRef) - { - [hidManager.deviceList removeObject:hidDevice]; - break; - } - } -} - -void HandleQueueValueAvailableCallback(void *inContext, IOReturn inResult, void *inSender) -{ - IOHIDQueueRef hidQueue = (IOHIDQueueRef)inSender; - NSMutableArray *inputAttributesList = nil; - NSAutoreleasePool *hidPool = [[NSAutoreleasePool alloc] init]; - - do - { - IOHIDValueRef hidValueRef = IOHIDQueueCopyNextValueWithTimeout(hidQueue, 0.0); - if (hidValueRef == NULL) - { - break; - } - - NSMutableArray *hatSwitchInput = [CocoaHIDDevice inputArrayFromHatSwitchValue:hidValueRef useEightDirection:NO]; - if (hatSwitchInput != nil) - { - inputAttributesList = hatSwitchInput; - } - else - { - inputAttributesList = [CocoaHIDDevice inputArrayFromHIDValue:hidValueRef]; - } - - if (inputAttributesList != nil) - { - // HID input devices don't register events, so we need to manually prevent - // sleep and screensaver whenever we detect an input. - UpdateSystemActivity(UsrActivity); - - [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"org.desmume.DeSmuME.hidInputDetected" object:inputAttributesList userInfo:nil]; - } - - CFRelease(hidValueRef); - } while (1); - - [hidPool release]; -} diff --git a/desmume/src/cocoa/cocoa_input.h b/desmume/src/cocoa/cocoa_input.h index 1c3dbeddf..106570fc8 100644 --- a/desmume/src/cocoa/cocoa_input.h +++ b/desmume/src/cocoa/cocoa_input.h @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2012 DeSmuME team + Copyright (C) 2012-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,75 +17,49 @@ */ #import -#include +#include @class CocoaDSMic; - -@interface CocoaDSInput : NSObject +enum { - NSMutableDictionary *map; - NSString *deviceCode; - NSString *deviceName; -} - -@property (retain) NSMutableDictionary *map; -@property (copy) NSString *deviceCode; -@property (copy) NSString *deviceName; - -- (id) initWithDeviceCode:(NSString *)theCode name:(NSString *)theName; - -- (void) set:(NSString *)elementCode attributes:(NSDictionary *)mappingAttributes; -- (NSDictionary *) mappingByElementCode:(NSString *)elementCode; -- (void) removeByElementCode:(NSString *)elementCode; -- (void) removeMapping:(NSString *)mappingName; - -+ (NSDictionary *) dictionaryWithMappingAttributes:(NSString *)mappingName - useDeviceValues:(BOOL)useDeviceValues - xPoint:(CGFloat)xPoint - yPoint:(CGFloat)yPoint - integerValue:(NSInteger)integerValue - floatValue:(float)floatValue - data:(NSData *)data - selector:(NSString *)selectorString - paramType:(NSString *)paramTypeKey; - -@end - + DSControllerState_Right = 0, + DSControllerState_Left, + DSControllerState_Down, + DSControllerState_Up, + DSControllerState_Select, + DSControllerState_Start, + DSControllerState_B, + DSControllerState_A, + DSControllerState_Y, + DSControllerState_X, + DSControllerState_L, + DSControllerState_R, + DSControllerState_Debug, + DSControllerState_Lid, + + DSControllerState_Touch, + DSControllerState_Microphone, + + DSControllerState_StatesCount +}; @interface CocoaDSController : NSObject { - NSMutableDictionary *states; CocoaDSMic *cdsMic; - pthread_mutex_t *mutexControllerUpdate; - NSMutableDictionary *inputs; + NSPoint touchLocation; + bool controllerState[DSControllerState_StatesCount]; + + OSSpinLock spinlockControllerState; } -@property (readonly) NSMutableDictionary *states; @property (retain) CocoaDSMic *cdsMic; -@property (readonly) NSMutableDictionary *inputs; -@property (readonly) pthread_mutex_t *mutexControllerUpdate; - (id) initWithMic:(CocoaDSMic *)theMic; -- (void) initDefaultMappings; -- (BOOL) initUserDefaultMappings; -- (void) initControllerMap; - -- (void) addMapping:(NSString *)controlName deviceInfo:(NSDictionary *)deviceInfo; - -- (BOOL) setStateWithInput:(NSDictionary *)inputAttributes; -- (BOOL) setStateWithMultipleInputs:(NSArray *)inputAttributesList; -- (NSDictionary *) mappingByEvent:(NSEvent *)event; -- (BOOL) updateController:(NSArray *)inputStates; - -- (NSDate *) inputTime:(NSString *)controlName; -- (bool) isInputPressed:(NSString *)controlName; -- (NSPoint) inputLocation:(NSString *)controlName; -- (unsigned char) inputSoundSample:(NSString *)controlName; - - (void) setSoundInputMode:(NSInteger)inputMode; -- (void) update; -- (void) handleHIDInput:(NSNotification *)aNotification; +- (void) setControllerState:(BOOL)theState controlID:(NSUInteger)controlID; +- (void) setTouchState:(BOOL)theState location:(NSPoint)theLocation; +- (void) flush; @end diff --git a/desmume/src/cocoa/cocoa_input.mm b/desmume/src/cocoa/cocoa_input.mm index f2a99bb6a..4a2c443e9 100644 --- a/desmume/src/cocoa/cocoa_input.mm +++ b/desmume/src/cocoa/cocoa_input.mm @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2012 DeSmuME team + Copyright (C) 2012-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,160 +25,9 @@ #undef BOOL -@implementation CocoaDSInput - -@synthesize map; -@synthesize deviceCode; -@synthesize deviceName; - -- (id)init -{ - return [self initWithDeviceCode:nil name:nil]; -} - -- (id) initWithDeviceCode:(NSString *)theCode name:(NSString *)theName -{ - self = [super init]; - if (self == nil) - { - return self; - } - - map = [[NSMutableDictionary alloc] initWithCapacity:32]; - - if (theCode == nil) - { - deviceCode = [[NSString stringWithFormat:@"0x%08X", arc4random()] retain]; - } - else - { - deviceCode = [theCode copy]; - } - - if (theName == nil) - { - deviceName = @"Unknown Device "; - deviceName = [[deviceName stringByAppendingString:deviceCode] retain]; - } - else - { - deviceName = [theName copy]; - } - - - return self; -} - -- (void)dealloc -{ - self.map = nil; - self.deviceCode = nil; - self.deviceName = nil; - - [super dealloc]; -} - -- (void) set:(NSString *)elementCode attributes:(NSDictionary *)mappingAttributes -{ - NSString *keyString = [[self.deviceCode stringByAppendingString:@":"] stringByAppendingString:elementCode]; - - // Remove any input mappings with the same DS control name as the new mapping. - // We're doing this check since the current UI doesn't support multiple bindings per control at this time. - // When the UI is updated to support multiple bindings per control, this check will need to be removed. - NSArray *mappingKeys = [self.map allKeys]; - for (NSString *key in mappingKeys) - { - NSDictionary *inputMapping = (NSDictionary *)[self.map valueForKey:key]; - NSString *dsControlName = (NSString *)[inputMapping valueForKey:@"name"]; - if ([dsControlName isEqualToString:(NSString *)[mappingAttributes valueForKey:@"name"]]) - { - [self.map setValue:nil forKey:key]; - } - } - - [self.map setValue:mappingAttributes forKey:keyString]; -} - -- (NSDictionary *) mappingByElementCode:(NSString *)elementCode -{ - NSString *keyString = [[self.deviceCode stringByAppendingString:@":"] stringByAppendingString:elementCode]; - return [self.map valueForKey:keyString]; -} - -- (void) removeByElementCode:(NSString *)elementCode -{ - NSString *keyString = [[self.deviceCode stringByAppendingString:@":"] stringByAppendingString:elementCode]; - [self.map setValue:nil forKey:keyString]; -} - -- (void) removeMapping:(NSString *)mappingName -{ - NSArray *mapKeys = [self.map allKeys]; - for(NSString *key in mapKeys) - { - if ([(NSString *)[(NSDictionary *)[self.map valueForKey:key] valueForKey:@"name"] isEqual:mappingName]) - { - [self.map removeObjectForKey:key]; - } - } -} - -+ (NSDictionary *) dictionaryWithMappingAttributes:(NSString *)mappingName - useDeviceValues:(BOOL)useDeviceValues - xPoint:(CGFloat)xPoint - yPoint:(CGFloat)yPoint - integerValue:(NSInteger)integerValue - floatValue:(float)floatValue - data:(NSData *)data - selector:(NSString *)selectorString - paramType:(NSString *)paramTypeKey -{ - NSDictionary *attributes = nil; - - if (mappingName == nil) - { - return attributes; - } - - if (useDeviceValues) - { - attributes = [NSDictionary dictionaryWithObjectsAndKeys: - mappingName, @"name", - [NSNumber numberWithBool:useDeviceValues], @"useDeviceValues", - nil]; - } - else - { - NSData *tempData = data; - if (tempData == nil) - { - tempData = [NSData data]; - } - - attributes = [NSDictionary dictionaryWithObjectsAndKeys: - mappingName, @"name", - [NSNumber numberWithBool:useDeviceValues], @"useDeviceValues", - [NSNumber numberWithFloat:xPoint], @"xPoint", - [NSNumber numberWithFloat:yPoint], @"yPoint", - [NSNumber numberWithInteger:integerValue], @"integerValue", - [NSNumber numberWithFloat:floatValue], @"floatValue", - tempData, @"data", - selectorString, @"selector", - paramTypeKey, @"paramType", - nil]; - } - - return attributes; -} - -@end - @implementation CocoaDSController -@synthesize states; @synthesize cdsMic; -@synthesize inputs; -@synthesize mutexControllerUpdate; - (id)init { @@ -193,447 +42,91 @@ return self; } - mutexControllerUpdate = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); - pthread_mutex_init(mutexControllerUpdate, NULL); + for (unsigned int i = 0; i < DSControllerState_StatesCount; i++) + { + controllerState[i] = false; + } + + spinlockControllerState = OS_SPINLOCK_INIT; cdsMic = [theMic retain]; - states = [[NSMutableDictionary alloc] init]; - inputs = [[NSMutableDictionary alloc] initWithCapacity:10]; - - [self initDefaultMappings]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleHIDInput:) - name:@"org.desmume.DeSmuME.hidInputDetected" - object:nil]; + touchLocation = NSMakePoint(0.0f, 0.0f); return self; } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - self.cdsMic = nil; - [states release]; - [inputs release]; - - pthread_mutex_destroy(self.mutexControllerUpdate); - free(self.mutexControllerUpdate); - mutexControllerUpdate = nil; [super dealloc]; } -- (void) initDefaultMappings -{ - [self initUserDefaultMappings]; - [self initControllerMap]; -} - -- (BOOL) initUserDefaultMappings -{ - BOOL didChange = NO; - - // Check to see if the DefaultKeyMappings.plist files exists. - NSDictionary *defaultMappings = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DefaultKeyMappings" ofType:@"plist"]]; - if (defaultMappings == nil) - { - return didChange; - } - - // If the input mappings does not exist in the user's preferences file, then copy all the mappings from the - // DefaultKeyMappings.plist file to the preferences file. Then we're done. - NSDictionary *userMappings = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"Input_ControllerMappings"]; - if (userMappings == nil) - { - [[NSUserDefaults standardUserDefaults] setObject:defaultMappings forKey:@"Input_ControllerMappings"]; - didChange = YES; - return didChange; - } - - // At this point, we need to check every key in the user's preference file and make sure that all the keys - // exist. The keys that must exist are all listed in the DefaultKeyMappings.plist file. - NSMutableDictionary *tempUserMappings = [NSMutableDictionary dictionaryWithDictionary:userMappings]; - - NSArray *inputKeys = [defaultMappings allKeys]; - for(NSString *inputString in inputKeys) - { - if ([tempUserMappings objectForKey:inputString] == nil) - { - [tempUserMappings setValue:[defaultMappings valueForKey:inputString] forKey:inputString]; - didChange = YES; - } - } - - // If we had to add a missing key, then we need to copy our temporary dictionary back to the - // user's preferences file. - if (didChange) - { - [[NSUserDefaults standardUserDefaults] setObject:tempUserMappings forKey:@"Input_ControllerMappings"]; - } - - // And we're done. - return didChange; -} - -- (void) initControllerMap -{ - NSDictionary *defaultMappings = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DefaultKeyMappings" ofType:@"plist"]]; - if (defaultMappings == nil) - { - return; - } - - NSDictionary *userMappings = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"Input_ControllerMappings"]; - if (userMappings == nil) - { - [self initUserDefaultMappings]; - } - - NSArray *controlNameList = [defaultMappings allKeys]; - for(NSString *controlName in controlNameList) - { - [self.states setValue:[NSMutableDictionary dictionaryWithCapacity:64] forKey:controlName]; - - NSArray *deviceInfoList = (NSArray *)[userMappings valueForKey:controlName]; - for(NSDictionary *deviceInfo in deviceInfoList) - { - [self addMapping:controlName deviceInfo:deviceInfo]; - } - } -} - -- (void) addMapping:(NSString *)controlName deviceInfo:(NSDictionary *)deviceInfo -{ - if (controlName == nil) - { - return; - } - - NSString *deviceCode = (NSString *)[deviceInfo valueForKey:@"deviceCode"]; - NSString *elementCode = (NSString *)[deviceInfo valueForKey:@"elementCode"]; - - if (deviceCode == nil || elementCode == nil) - { - return; - } - - NSDictionary *mappingAttributes = [CocoaDSInput dictionaryWithMappingAttributes:controlName - useDeviceValues:[(NSNumber *)[deviceInfo valueForKey:@"useDeviceValues"] boolValue] - xPoint:[(NSNumber *)[deviceInfo valueForKey:@"xPoint"] floatValue] - yPoint:[(NSNumber *)[deviceInfo valueForKey:@"yPoint"] floatValue] - integerValue:[(NSNumber *)[deviceInfo valueForKey:@"integerValue"] integerValue] - floatValue:[(NSNumber *)[deviceInfo valueForKey:@"floatValue"] floatValue] - data:(NSData *)[deviceInfo valueForKey:@"data"] - selector:(NSString *)[deviceInfo valueForKey:@"selector"] - paramType:(NSString *)[deviceInfo valueForKey:@"paramType"]]; - - if (mappingAttributes == nil) - { - return; - } - - CocoaDSInput *input = (CocoaDSInput *)[self.inputs valueForKey:deviceCode]; - if (input == nil) - { - NSString *deviceName = (NSString *)[deviceInfo valueForKey:@"deviceName"]; - if (deviceName == nil) - { - deviceName = deviceCode; - } - - input = [[[CocoaDSInput alloc] initWithDeviceCode:deviceCode name:deviceName] autorelease]; - [self.inputs setValue:input forKey:deviceCode]; - } - - [input set:elementCode attributes:mappingAttributes]; -} - -- (BOOL) setStateWithInput:(NSDictionary *)inputAttributes -{ - BOOL inputChanged = NO; - - if (inputAttributes == nil) - { - return inputChanged; - } - - NSMutableArray *attributesList = [NSMutableArray arrayWithObject:inputAttributes]; - - return [self setStateWithMultipleInputs:attributesList]; -} - -- (BOOL) setStateWithMultipleInputs:(NSArray *)inputAttributesList -{ - BOOL inputChanged = NO; - NSMutableArray *inputStates = [NSMutableArray arrayWithCapacity:8]; - - if (inputAttributesList == nil || [inputAttributesList count] <= 0) - { - return inputChanged; - } - - for (NSDictionary *attr in inputAttributesList) - { - NSString *deviceCode = (NSString *)[attr valueForKey:@"deviceCode"]; - if (deviceCode == nil) - { - continue; - } - - NSString *elementCode = (NSString *)[attr valueForKey:@"elementCode"]; - if (elementCode == nil) - { - continue; - } - - CocoaDSInput *input = (CocoaDSInput *)[self.inputs valueForKey:deviceCode]; - if (input == nil) - { - continue; - } - - NSDictionary *mappingAttributes = [input mappingByElementCode:elementCode]; - if (mappingAttributes == nil) - { - continue; - } - - NSString *controlName = (NSString *)[mappingAttributes valueForKey:@"name"]; - if (controlName == nil) - { - continue; - } - - NSMutableDictionary *inputState = [NSMutableDictionary dictionaryWithObjectsAndKeys: - controlName, @"name", - [attr valueForKey:@"on"], @"on", - nil]; - - NSNumber *xPointNumber = nil; - NSNumber *yPointNumber = nil; - NSNumber *integerNumber = nil; - NSNumber *floatNumber = nil; - NSData *inputData = nil; - NSString *selectorString = nil; - NSString *paramTypeKey = nil; - - NSNumber *useDeviceValuesNumber = (NSNumber *)[mappingAttributes valueForKey:@"useDeviceValues"]; - if (useDeviceValuesNumber == nil || ![useDeviceValuesNumber boolValue]) // Not reading from device values, use values from mapping attributes - { - xPointNumber = (NSNumber *)[mappingAttributes valueForKey:@"pointX"]; - yPointNumber = (NSNumber *)[mappingAttributes valueForKey:@"pointY"]; - integerNumber = (NSNumber *)[mappingAttributes valueForKey:@"integerValue"]; - floatNumber = (NSNumber *)[mappingAttributes valueForKey:@"floatValue"]; - inputData = (NSData *)[mappingAttributes valueForKey:@"data"]; - selectorString = (NSString *)[mappingAttributes valueForKey:@"selector"]; - paramTypeKey = (NSString *)[mappingAttributes valueForKey:@"paramType"]; - } - else // Reading from device values, use values from input attributes - { - xPointNumber = (NSNumber *)[attr valueForKey:@"pointX"]; - yPointNumber = (NSNumber *)[attr valueForKey:@"pointY"]; - integerNumber = (NSNumber *)[attr valueForKey:@"integerValue"]; - floatNumber = (NSNumber *)[attr valueForKey:@"floatValue"]; - inputData = (NSData *)[attr valueForKey:@"data"]; - } - - if (xPointNumber == nil) - { - xPointNumber = [NSNumber numberWithFloat:0.0f]; - } - - if (yPointNumber == nil) - { - yPointNumber = [NSNumber numberWithFloat:0.0f]; - } - - if (integerNumber == nil) - { - integerNumber = [NSNumber numberWithInteger:0]; - } - - if (floatNumber == nil) - { - floatNumber = [NSNumber numberWithFloat:0.0f]; - } - - [inputState setValue:xPointNumber forKey:@"pointX"]; - [inputState setValue:yPointNumber forKey:@"pointY"]; - [inputState setValue:integerNumber forKey:@"integerValue"]; - [inputState setValue:floatNumber forKey:@"floatValue"]; - [inputState setValue:inputData forKey:@"data"]; - - [inputStates addObject:inputState]; - } - - inputChanged = [self updateController:inputStates]; - - return inputChanged; -} - -- (NSDictionary *) mappingByEvent:(NSEvent *)event -{ - CocoaDSInput *input = nil; - NSString *elementCode = nil; - NSEventType eventType = [event type]; - - switch (eventType) - { - case NSKeyDown: - case NSKeyUp: - input = (CocoaDSInput *)[self.inputs valueForKey:@"NSEventKeyboard"]; - elementCode = [NSString stringWithFormat:@"%d", [event keyCode]]; - break; - - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - input = (CocoaDSInput *)[self.inputs valueForKey:@"NSEventMouse"]; - elementCode = [NSString stringWithFormat:@"%li", (long)[event buttonNumber]]; - break; - - default: - break; - } - - return [input mappingByElementCode:elementCode]; -} - -- (BOOL) updateController:(NSArray *)inputStates -{ - BOOL result = NO; - - if (inputStates == nil) - { - return result; - } - - pthread_mutex_lock(self.mutexControllerUpdate); - - for (NSDictionary *iState in inputStates) - { - NSString *controlName = (NSString *)[iState valueForKey:@"name"]; - if (controlName == nil) - { - continue; - } - - NSMutableDictionary *controlState = (NSMutableDictionary *)[self.states valueForKey:controlName]; - [controlState setDictionary:iState]; - [controlState setValue:[NSDate date] forKey:@"time"]; - - result = YES; - } - - pthread_mutex_unlock(self.mutexControllerUpdate); - - return result; -} - -- (NSDate *) inputTime:(NSString *)controlName -{ - NSDate *inputTime = nil; - - NSMutableDictionary *properties = [self.states objectForKey:controlName]; - inputTime = [properties objectForKey:@"time"]; - if (inputTime == nil) - { - return inputTime; - } - - return inputTime; -} - -- (bool) isInputPressed:(NSString *)controlName -{ - bool result = false; - - NSMutableDictionary *controlState = (NSMutableDictionary *)[self.states valueForKey:controlName]; - NSNumber *pressValue = (NSNumber *)[controlState valueForKey:@"on"]; - if (pressValue == nil) - { - return result; - } - - result = [pressValue boolValue]; - - return result; -} - -- (NSPoint) inputLocation:(NSString *)controlName -{ - NSPoint outPoint = {0.0f, 0.0f}; - NSMutableDictionary *properties = [self.states objectForKey:controlName]; - - NSNumber *xValue = [properties objectForKey:@"pointX"]; - if (xValue != nil) - { - outPoint.x = [xValue floatValue]; - } - - NSNumber *yValue = [properties objectForKey:@"pointY"]; - if (yValue != nil) - { - outPoint.y = [yValue floatValue]; - } - - return outPoint; -} - -- (unsigned char) inputSoundSample:(NSString *)controlName -{ - unsigned char sampleValue = 0; - - NSMutableDictionary *properties = [self.states objectForKey:controlName]; - NSNumber *sampleValueObj = [properties objectForKey:@"Sound Sample"]; - if (sampleValueObj == nil) - { - return sampleValue; - } - - sampleValue = [sampleValueObj unsignedCharValue]; - - return sampleValue; -} - - (void) setSoundInputMode:(NSInteger)inputMode { + OSSpinLockLock(&spinlockControllerState); self.cdsMic.mode = inputMode; + OSSpinLockUnlock(&spinlockControllerState); } -- (void) update +- (void) setControllerState:(BOOL)theState controlID:(NSUInteger)controlID { - pthread_mutex_lock(self.mutexControllerUpdate); + if (controlID >= DSControllerState_StatesCount) + { + return; + } + + OSSpinLockLock(&spinlockControllerState); + controllerState[controlID] = (theState) ? true : false; + OSSpinLockUnlock(&spinlockControllerState); +} + +- (void) setTouchState:(BOOL)theState location:(NSPoint)theLocation +{ + OSSpinLockLock(&spinlockControllerState); + controllerState[DSControllerState_Touch] = (theState) ? true : false; + touchLocation = theLocation; + OSSpinLockUnlock(&spinlockControllerState); +} + +- (void) flush +{ + OSSpinLockLock(&spinlockControllerState); + + NSPoint theLocation = touchLocation; + NSInteger micMode = cdsMic.mode; + bool flushedStates[DSControllerState_StatesCount] = {0}; + + for (unsigned int i = 0; i < DSControllerState_StatesCount; i++) + { + flushedStates[i] = controllerState[i]; + } + + OSSpinLockUnlock(&spinlockControllerState); + + bool isTouchDown = flushedStates[DSControllerState_Touch]; + bool isMicPressed = flushedStates[DSControllerState_Microphone]; // Setup the DS pad. - NDS_setPad([self isInputPressed:@"Right"], - [self isInputPressed:@"Left"], - [self isInputPressed:@"Down"], - [self isInputPressed:@"Up"], - [self isInputPressed:@"Select"], - [self isInputPressed:@"Start"], - [self isInputPressed:@"B"], - [self isInputPressed:@"A"], - [self isInputPressed:@"Y"], - [self isInputPressed:@"X"], - [self isInputPressed:@"L"], - [self isInputPressed:@"R"], - [self isInputPressed:@"Debug"], - [self isInputPressed:@"Lid"]); + NDS_setPad(flushedStates[DSControllerState_Right], + flushedStates[DSControllerState_Left], + flushedStates[DSControllerState_Down], + flushedStates[DSControllerState_Up], + flushedStates[DSControllerState_Select], + flushedStates[DSControllerState_Start], + flushedStates[DSControllerState_B], + flushedStates[DSControllerState_A], + flushedStates[DSControllerState_Y], + flushedStates[DSControllerState_X], + flushedStates[DSControllerState_L], + flushedStates[DSControllerState_R], + flushedStates[DSControllerState_Debug], + flushedStates[DSControllerState_Lid]); // Setup the DS touch pad. - if ([self isInputPressed:@"Touch"]) + if (isTouchDown) { - NSPoint touchLocation = [self inputLocation:@"Touch"]; - NDS_setTouchPos((u16)touchLocation.x, (u16)touchLocation.y); + NDS_setTouchPos((u16)theLocation.x, (u16)theLocation.y); } else { @@ -641,37 +134,27 @@ } // Setup the DS mic. - bool isMicPressed = [self isInputPressed:@"Microphone"]; NDS_setMic(isMicPressed); - pthread_mutex_unlock(self.mutexControllerUpdate); - if (isMicPressed) { - if (self.cdsMic.mode == MICMODE_NONE) + if (micMode == MICMODE_NONE) { [self.cdsMic fillWithNullSamples]; } - else if (self.cdsMic.mode == MICMODE_INTERNAL_NOISE) + else if (micMode == MICMODE_INTERNAL_NOISE) { [self.cdsMic fillWithInternalNoise]; } - else if (self.cdsMic.mode == MICMODE_WHITE_NOISE) + else if (micMode == MICMODE_WHITE_NOISE) { [self.cdsMic fillWithWhiteNoise]; } - else if (self.cdsMic.mode == MICMODE_SOUND_FILE) + else if (micMode == MICMODE_SOUND_FILE) { // TODO: Need to implement. Does nothing for now. } } } -- (void) handleHIDInput:(NSNotification *)aNotification -{ - NSArray *inputPropertiesList = (NSArray *)[aNotification object]; - - [self setStateWithMultipleInputs:inputPropertiesList]; -} - @end diff --git a/desmume/src/cocoa/cocoa_mic.mm b/desmume/src/cocoa/cocoa_mic.mm index 4eff07246..b8aaf6cc6 100644 --- a/desmume/src/cocoa/cocoa_mic.mm +++ b/desmume/src/cocoa/cocoa_mic.mm @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2012 DeSmuME team + Copyright (C) 2012-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,7 +31,7 @@ static CocoaDSMic *masterMic = nil; @synthesize writePosition; @synthesize fillCount; @synthesize needsActivate; -@synthesize mode; +@dynamic mode; - (id)init { @@ -73,7 +73,12 @@ static CocoaDSMic *masterMic = nil; [super dealloc]; } -- (void) mode:(NSInteger)theMode +- (NSInteger) mode +{ + return mode; +} + +- (void) setMode:(NSInteger)theMode { switch (theMode) { @@ -100,6 +105,8 @@ static CocoaDSMic *masterMic = nil; default: break; } + + mode = theMode; } - (void) clear diff --git a/desmume/src/cocoa/translations/English.lproj/DisplayWindow.xib b/desmume/src/cocoa/translations/English.lproj/DisplayWindow.xib index 3f550d5b8..6b0f40dc2 100644 --- a/desmume/src/cocoa/translations/English.lproj/DisplayWindow.xib +++ b/desmume/src/cocoa/translations/English.lproj/DisplayWindow.xib @@ -12,7 +12,7 @@ YES - + YES @@ -632,14 +632,6 @@ 58 - - - executeCoreToggle: - - - - 59 - openRom: @@ -648,14 +640,6 @@ 60 - - - resetCore: - - - - 61 - delegate @@ -803,6 +787,22 @@ 106 + + + reset: + + + + 107 + + + + toggleExecutePause: + + + + 108 + @@ -1137,7 +1137,7 @@ {3.40282e+38, 3.40282e+38} {256, 408} - {{1056, 575}, {616, 0}} + {{1136, 494}, {616, 227}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1190,7 +1190,7 @@ - 106 + 108 @@ -1214,10 +1214,10 @@ changeRotationRelative: changeVolume: copy: - executeCoreToggle: openRom: - resetCore: + reset: saveScreenshotAs: + toggleExecutePause: toggleKeepMinDisplaySizeAtNormal: toggleStatusBar: @@ -1243,10 +1243,10 @@ changeRotationRelative: changeVolume: copy: - executeCoreToggle: openRom: - resetCore: + reset: saveScreenshotAs: + toggleExecutePause: toggleKeepMinDisplaySizeAtNormal: toggleStatusBar: @@ -1268,22 +1268,22 @@ copy: id - - executeCoreToggle: - id - openRom: id - resetCore: + reset: id saveScreenshotAs: id + + toggleExecutePause: + id + toggleKeepMinDisplaySizeAtNormal: id diff --git a/desmume/src/cocoa/translations/English.lproj/MainMenu.xib b/desmume/src/cocoa/translations/English.lproj/MainMenu.xib index ec469b063..d3e6f2103 100644 --- a/desmume/src/cocoa/translations/English.lproj/MainMenu.xib +++ b/desmume/src/cocoa/translations/English.lproj/MainMenu.xib @@ -12,7 +12,7 @@ YES - + YES @@ -3481,6 +3481,9 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA EmuControllerDelegate + + InputManager + 15 2 @@ -4833,7 +4836,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA NSView - + 268 YES @@ -4842,6 +4845,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 12 {{13, 10}, {614, 409}} + YES @@ -4856,6 +4860,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 340}, {452, 21}} + YES 75628096 @@ -4874,6 +4879,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 315}, {452, 21}} + YES 75628096 @@ -4892,6 +4898,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 290}, {452, 21}} + YES 75628096 @@ -4910,6 +4917,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 265}, {452, 21}} + YES 75628096 @@ -4928,6 +4936,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 240}, {452, 21}} + YES 75628096 @@ -4946,6 +4955,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 215}, {452, 21}} + YES 75628096 @@ -4964,6 +4974,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 190}, {452, 21}} + YES 75628096 @@ -4982,6 +4993,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 165}, {452, 21}} + YES 75628096 @@ -5000,6 +5012,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 140}, {452, 21}} + YES 75628096 @@ -5018,6 +5031,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 115}, {452, 21}} + YES 75628096 @@ -5036,6 +5050,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 90}, {452, 21}} + YES 75628096 @@ -5054,6 +5069,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 65}, {452, 21}} + YES 75628096 @@ -5072,6 +5088,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 340}, {100, 19}} + 1000 YES @@ -5094,6 +5111,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 315}, {100, 19}} + 1001 YES @@ -5116,6 +5134,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 290}, {100, 19}} + 1002 YES @@ -5138,6 +5157,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 265}, {100, 19}} + 1003 YES @@ -5160,6 +5180,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 240}, {100, 19}} + 1004 YES @@ -5182,6 +5203,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 215}, {100, 19}} + 1005 YES @@ -5204,6 +5226,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 190}, {100, 19}} + 1006 YES @@ -5226,6 +5249,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 165}, {100, 19}} + 1007 YES @@ -5248,6 +5272,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 140}, {100, 19}} + 1008 YES @@ -5270,6 +5295,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 115}, {100, 19}} + 1009 YES @@ -5292,6 +5318,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 90}, {100, 19}} + 1010 YES @@ -5314,6 +5341,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 65}, {100, 19}} + 1011 YES @@ -5336,6 +5364,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 40}, {100, 19}} + 3000 YES @@ -5358,6 +5387,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 40}, {452, 21}} + YES 75628096 @@ -5376,6 +5406,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{125, 15}, {452, 21}} + YES 75628096 @@ -5394,6 +5425,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA 268 {{17, 15}, {100, 19}} + 3001 YES @@ -5414,6 +5446,7 @@ aGVhdHMuZ2JhdGVtcC5uZXQvA {{10, 33}, {594, 363}} + Controller @@ -5927,6 +5960,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {640, 433} + + InputPrefsView @@ -10637,7 +10672,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {1.79769e+308, 1.79769e+308} - + 256 YES @@ -10656,12 +10691,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 256 {270, 321} + YES 256 {270, 17} + @@ -10669,6 +10706,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA -2147483392 {{256, 0}, {16, 17}} + YES @@ -10778,6 +10816,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 17}, {270, 321}} + @@ -10788,6 +10827,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA -2147483392 {{256, 17}, {15, 306}} + _doScroller: 0.99689440993788825 @@ -10797,6 +10837,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA -2147483392 {{1, 323}, {270, 15}} + 1 _doScroller: @@ -10811,6 +10852,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 0}, {270, 17}} + @@ -10820,6 +10862,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{20, 49}, {272, 339}} + 562 @@ -10834,6 +10877,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{113, 12}, {185, 32}} + YES 67239424 @@ -10854,6 +10898,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{47, 19}, {28, 23}} + YES -2080244224 @@ -10875,6 +10920,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{20, 19}, {28, 23}} + YES -2080244224 @@ -10906,6 +10952,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{100, 372}, {209, 26}} + YES -2076049856 @@ -10970,6 +11017,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 301 {{2, 33}, {320, 290}} + NSView @@ -10977,6 +11025,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 402}, {129, 18}} + YES 67239424 @@ -10999,6 +11048,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{15, 378}, {83, 17}} + YES 68288064 @@ -11019,6 +11069,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 12 {{14, 320}, {292, 5}} + {0, 0} 67239424 @@ -11041,6 +11092,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{103, 331}, {203, 39}} + YES -1805517311 @@ -11058,6 +11110,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{15, 353}, {83, 17}} + YES 68288064 @@ -11074,6 +11127,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{114, 6}, {96, 32}} + YES 67239424 @@ -11092,10 +11146,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {324, 428}} + {{297, 16}, {326, 444}} + {0, 0} 67239424 @@ -11119,6 +11175,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{89, 446}, {70, 14}} + YES 68288064 @@ -11139,6 +11196,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{89, 421}, {69, 14}} + YES 68288064 @@ -11155,6 +11213,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{160, 421}, {135, 14}} + YES 70385217 @@ -11172,6 +11231,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{161, 446}, {134, 14}} + YES 70385217 @@ -11189,6 +11249,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{90, 394}, {190, 18}} + YES -2080244224 @@ -11223,6 +11284,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{20, 396}, {64, 64}} + YES 130560 @@ -11237,6 +11299,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {640, 480} + + {{0, 0}, {1920, 1178}} {1.79769e+308, 1.79769e+308} @@ -13040,7 +13104,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {1.79769e+308, 1.79769e+308} - + 256 YES @@ -13059,6 +13123,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 32}, {171, 18}} + 1 YES @@ -13082,6 +13147,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 12}, {187, 18}} + 10 YES @@ -13103,10 +13169,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {244, 58}} + {{17, 404}, {246, 74}} + {0, 0} 67239424 @@ -13140,6 +13208,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 52}, {158, 18}} + 2 YES @@ -13163,6 +13232,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{35, 32}, {120, 18}} + 3 YES @@ -13186,6 +13256,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{35, 12}, {132, 18}} + 4 YES @@ -13207,10 +13278,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {244, 78}} + {{17, 224}, {246, 94}} + {0, 0} 67239424 @@ -13244,6 +13317,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{15, 32}, {177, 18}} + 5 YES @@ -13267,6 +13341,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{15, 12}, {130, 18}} + 6 YES @@ -13290,6 +13365,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 265 {{176, 54}, {27, 27}} + YES -2080244224 @@ -13311,6 +13387,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{15, 61}, {157, 14}} + YES 68288064 @@ -13325,10 +13402,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {244, 85}} + {{17, 119}, {246, 101}} + {0, 0} 67239424 @@ -13352,6 +13431,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{63, 18}, {154, 19}} + YES -2080244224 @@ -13382,6 +13462,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{15, 32}, {127, 18}} + 9 YES @@ -13405,6 +13486,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{15, 12}, {103, 18}} + YES 67239424 @@ -13425,10 +13507,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {244, 58}} + {{17, 41}, {246, 74}} + {0, 0} 67239424 @@ -13462,6 +13546,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 14}, {145, 38}} + YES 2 1 @@ -13652,10 +13737,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {244, 62}} + {{17, 322}, {246, 78}} + {0, 0} 67239424 @@ -13676,6 +13763,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {280, 498} + + {{0, 0}, {1920, 1178}} {1.79769e+308, 1.79769e+308} @@ -14205,7 +14294,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {1.79769e+308, 1.79769e+308} - + 256 YES @@ -14214,6 +14303,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 174}, {158, 18}} + YES -2080244224 @@ -14236,6 +14326,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 154}, {158, 18}} + YES -2080244224 @@ -14258,6 +14349,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 134}, {158, 18}} + YES -2080244224 @@ -14280,6 +14372,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 114}, {158, 18}} + YES -2080244224 @@ -14302,6 +14395,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 94}, {158, 18}} + YES -2080244224 @@ -14324,6 +14418,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 74}, {158, 18}} + YES -2080244224 @@ -14346,6 +14441,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 54}, {158, 18}} + YES -2080244224 @@ -14368,6 +14464,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{20, 18}, {154, 19}} + YES -2080244224 @@ -14388,6 +14485,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 205}, {158, 18}} + YES -2080244224 @@ -14410,6 +14508,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 12 {{21, 196}, {153, 5}} + {0, 0} 67239424 @@ -14429,6 +14528,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {194, 241} + + {{0, 0}, {1920, 1178}} {1.79769e+308, 1.79769e+308} @@ -14443,7 +14544,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {1.79769e+308, 1.79769e+308} - + 256 YES @@ -14452,6 +14553,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{20, 18}, {164, 19}} + YES -2080244224 @@ -14482,6 +14584,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{18, 14}, {129, 378}} + YES 19 1 @@ -14979,10 +15082,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {168, 402}} + {{17, 41}, {170, 418}} + {0, 0} 67239424 @@ -15006,6 +15111,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{17, 485}, {169, 18}} + YES -2080244224 @@ -15028,6 +15134,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{17, 465}, {135, 18}} + YES 67239424 @@ -15047,6 +15154,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {204, 521} + + {{0, 0}, {1920, 1178}} {1.79769e+308, 1.79769e+308} @@ -27389,30 +27498,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 6716 - - - speedLimitDisable: - - - - 6717 - - - - resetCore: - - - - 6718 - - - - executeCoreToggle: - - - - 6719 - changeCoreEmuFlags: @@ -27597,14 +27682,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 6745 - - - cheatsDisable: - - - - 6746 - changeCoreSpeed: @@ -29188,14 +29265,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 6994 - - - copy: - - - - 6995 - saveScreenshotAs: @@ -29228,6 +29297,78 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 7001 + + + emuControl + + + + 7003 + + + + inputManager + + + + 7004 + + + + inputManager + + + + 7005 + + + + inputManager + + + + 7006 + + + + toggleExecutePause: + + + + 7009 + + + + reset: + + + + 7010 + + + + copy: + + + + 7011 + + + + toggleCheats: + + + + 7012 + + + + toggleSpeedLimiter: + + + + 7013 + @@ -40080,6 +40221,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + 7002 + + + @@ -42103,6 +42249,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 6931.IBPluginDependency 6998.IBPluginDependency 6999.IBPluginDependency + 7002.IBPluginDependency 714.IBEditorWindowLastContentRect 714.IBPluginDependency 714.IBViewBoundsToFrameTransform @@ -46293,6 +46440,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin {{1271, 124}, {328, 434}} com.apple.InterfaceBuilder.CocoaPlugin @@ -46641,7 +46789,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - 7001 + 7013 @@ -46732,6 +46880,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA cheatWindowController emuControlController fileMigrationList + inputManager inputPrefsView mLoadStateSlot mSaveStateSlot @@ -46756,6 +46905,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSObjectController NSObjectController NSArrayController + InputManager InputPrefsView NSMenu NSMenu @@ -46783,6 +46933,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA cheatWindowController emuControlController fileMigrationList + inputManager inputPrefsView mLoadStateSlot mSaveStateSlot @@ -46843,6 +46994,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA fileMigrationList NSArrayController + + inputManager + InputManager + inputPrefsView InputPrefsView @@ -47161,6 +47316,139 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA userinterface/cheatWindowDelegate.h + + DisplayView + NSView + + IBProjectSource + userinterface/DisplayWindowController.h + + + + DisplayWindowController + NSWindowController + + YES + + YES + changeCoreSpeed: + changeRotationRelative: + changeVolume: + copy: + openRom: + reset: + saveScreenshotAs: + toggleExecutePause: + toggleKeepMinDisplaySizeAtNormal: + toggleStatusBar: + + + YES + id + id + id + id + id + id + id + id + id + id + + + + YES + + YES + changeCoreSpeed: + changeRotationRelative: + changeVolume: + copy: + openRom: + reset: + saveScreenshotAs: + toggleExecutePause: + toggleKeepMinDisplaySizeAtNormal: + toggleStatusBar: + + + YES + + changeCoreSpeed: + id + + + changeRotationRelative: + id + + + changeVolume: + id + + + copy: + id + + + openRom: + id + + + reset: + id + + + saveScreenshotAs: + id + + + toggleExecutePause: + id + + + toggleKeepMinDisplaySizeAtNormal: + id + + + toggleStatusBar: + id + + + + + YES + + YES + saveScreenshotPanelAccessoryView + view + + + YES + NSView + DisplayView + + + + YES + + YES + saveScreenshotPanelAccessoryView + view + + + YES + + saveScreenshotPanelAccessoryView + NSView + + + view + DisplayView + + + + + EmuControllerDelegate NSObject @@ -47184,30 +47472,29 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA changeSpuSyncMethod: changeSpuSyncMode: changeVolume: - cheatsDisable: closeRom: closeSheet: closeWindow: copy: - executeCoreToggle: exportRomSave: importRomSave: loadEmuSaveStateSlot: newDisplayWindow: openEmuSaveState: openRom: - resetCore: + reset: revertEmuSaveState: runToolbarCustomizationPalette: saveEmuSaveState: saveEmuSaveStateAs: saveEmuSaveStateSlot: saveScreenshotAs: - selectExportRomSaveFormat: - speedLimitDisable: toggleAutoFrameSkip: + toggleCheats: + toggleExecutePause: toggleGPUState: toggleKeepMinDisplaySizeAtNormal: + toggleSpeedLimiter: toggleStatusBar: toggleToolbarShown: writeDefaults3DRenderingSettings: @@ -47266,7 +47553,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA id id id - id @@ -47289,30 +47575,29 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA changeSpuSyncMethod: changeSpuSyncMode: changeVolume: - cheatsDisable: closeRom: closeSheet: closeWindow: copy: - executeCoreToggle: exportRomSave: importRomSave: loadEmuSaveStateSlot: newDisplayWindow: openEmuSaveState: openRom: - resetCore: + reset: revertEmuSaveState: runToolbarCustomizationPalette: saveEmuSaveState: saveEmuSaveStateAs: saveEmuSaveStateSlot: saveScreenshotAs: - selectExportRomSaveFormat: - speedLimitDisable: toggleAutoFrameSkip: + toggleCheats: + toggleExecutePause: toggleGPUState: toggleKeepMinDisplaySizeAtNormal: + toggleSpeedLimiter: toggleStatusBar: toggleToolbarShown: writeDefaults3DRenderingSettings: @@ -47388,10 +47673,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA changeVolume: id - - cheatsDisable: - id - closeRom: id @@ -47408,10 +47689,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA copy: id - - executeCoreToggle: - id - exportRomSave: id @@ -47437,7 +47714,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA id - resetCore: + reset: id @@ -47464,18 +47741,18 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA saveScreenshotAs: id - - selectExportRomSaveFormat: - id - - - speedLimitDisable: - id - toggleAutoFrameSkip: id + + toggleCheats: + id + + + toggleExecutePause: + id + toggleGPUState: id @@ -47484,6 +47761,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA toggleKeepMinDisplaySizeAtNormal: id + + toggleSpeedLimiter: + id + toggleStatusBar: id @@ -47530,6 +47811,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA cheatWindowDelegate exportRomSavePanelAccessoryView firmwarePanelController + inputManager romInfoPanelController saveFileMigrationSheet saveStatePrecloseSheet @@ -47544,6 +47826,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA CheatWindowDelegate NSView NSObjectController + InputManager NSObjectController NSWindow NSWindow @@ -47561,6 +47844,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA cheatWindowDelegate exportRomSavePanelAccessoryView firmwarePanelController + inputManager romInfoPanelController saveFileMigrationSheet saveStatePrecloseSheet @@ -47599,6 +47883,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA firmwarePanelController NSObjectController + + inputManager + InputManager + romInfoPanelController NSObjectController @@ -47618,6 +47906,92 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA userinterface/EmuControllerDelegate.h + + InputManager + NSObject + + YES + + YES + changeCoreSpeed: + changeVolume: + saveScreenshotAs: + toggleGPUState: + + + YES + id + id + id + id + + + + YES + + YES + changeCoreSpeed: + changeVolume: + saveScreenshotAs: + toggleGPUState: + + + YES + + changeCoreSpeed: + id + + + changeVolume: + id + + + saveScreenshotAs: + id + + + toggleGPUState: + id + + + + + YES + + YES + emuControl + hidInputTarget + + + YES + EmuControllerDelegate + id + + + + YES + + YES + emuControl + hidInputTarget + + + YES + + emuControl + EmuControllerDelegate + + + hidInputTarget + id + + + + + IBProjectSource + userinterface/InputManager.h + + InputPrefsView NSView @@ -47633,14 +48007,35 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - prefWindow - NSWindow + YES + + YES + inputManager + prefWindow + + + YES + InputManager + NSWindow + - prefWindow - - prefWindow - NSWindow + YES + + YES + inputManager + prefWindow + + + YES + + inputManager + InputManager + + + prefWindow + NSWindow + @@ -48856,6 +49251,25 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA AppKit.framework/Headers/NSWindowScripting.h + + NSWindowController + NSResponder + + showWindow: + id + + + showWindow: + + showWindow: + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSWindowController.h + + 0 diff --git a/desmume/src/cocoa/userinterface/DisplayWindowController.h b/desmume/src/cocoa/userinterface/DisplayWindowController.h index c3235c576..2514f3838 100644 --- a/desmume/src/cocoa/userinterface/DisplayWindowController.h +++ b/desmume/src/cocoa/userinterface/DisplayWindowController.h @@ -19,15 +19,16 @@ #include #include +#import "InputManager.h" #import "cocoa_output.h" @class CocoaDSController; @class EmuControllerDelegate; -@interface DisplayView : NSView +@interface DisplayView : NSView { - CocoaDSController *cdsController; + InputManager *inputManager; // Display thread BOOL isHudEnabled; @@ -64,7 +65,7 @@ unsigned int vtxBufferOffset; } -@property (retain) CocoaDSController *cdsController; +@property (retain) InputManager *inputManager; - (void) startupOpenGL; - (void) shutdownOpenGL; @@ -143,7 +144,6 @@ - (id)initWithWindowNibName:(NSString *)windowNibName emuControlDelegate:(EmuControllerDelegate *)theEmuController; -- (void) setCdsController:(CocoaDSController *)theController; - (void) setupUserDefaults; - (double) resizeWithTransform:(NSSize)normalBounds scalar:(double)scalar rotation:(double)angleDegrees; - (double) maxContentScalar:(NSSize)contentBounds; @@ -153,8 +153,8 @@ - (IBAction) toggleKeepMinDisplaySizeAtNormal:(id)sender; - (IBAction) toggleStatusBar:(id)sender; -- (IBAction) executeCoreToggle:(id)sender; -- (IBAction) resetCore:(id)sender; +- (IBAction) toggleExecutePause:(id)sender; +- (IBAction) reset:(id)sender; - (IBAction) changeCoreSpeed:(id)sender; - (IBAction) openRom:(id)sender; - (IBAction) changeRotationRelative:(id)sender; diff --git a/desmume/src/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/cocoa/userinterface/DisplayWindowController.mm index 3c72c7e42..e290e6945 100644 --- a/desmume/src/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/cocoa/userinterface/DisplayWindowController.mm @@ -17,6 +17,7 @@ #import "DisplayWindowController.h" #import "EmuControllerDelegate.h" +#import "InputManager.h" #import "cocoa_file.h" #import "cocoa_input.h" @@ -508,11 +509,6 @@ enum OGLVertexAttributeID #pragma mark Class Methods -- (void) setCdsController:(CocoaDSController *)theController -{ - [view setCdsController:theController]; -} - - (void) setupUserDefaults { // Set the display window per user preferences. @@ -639,14 +635,14 @@ enum OGLVertexAttributeID [self setIsShowingStatusBar:([self isShowingStatusBar]) ? NO : YES]; } -- (IBAction) executeCoreToggle:(id)sender +- (IBAction) toggleExecutePause:(id)sender { - [emuControl executeCoreToggle:sender]; + [emuControl toggleExecutePause:sender]; } -- (IBAction) resetCore:(id)sender +- (IBAction) reset:(id)sender { - [emuControl resetCore:sender]; + [emuControl reset:sender]; } - (IBAction) changeCoreSpeed:(id)sender @@ -705,6 +701,7 @@ enum OGLVertexAttributeID { [emuControl setMainWindow:self]; [view setNextResponder:[self window]]; + [[view inputManager] setHidInputTarget:view]; } - (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize @@ -783,7 +780,7 @@ enum OGLVertexAttributeID BOOL enable = YES; const SEL theAction = [theItem action]; - if (theAction == @selector(executeCoreToggle:)) + if (theAction == @selector(toggleExecutePause:)) { if (![emuControl masterExecuteFlag] || [emuControl currentRom] == nil || @@ -803,7 +800,7 @@ enum OGLVertexAttributeID [theItem setImage:[emuControl iconPause]]; } } - else if (theAction == @selector(resetCore:)) + else if (theAction == @selector(reset:)) { if ([emuControl currentRom] == nil || [emuControl isUserInterfaceBlockingExecution]) { @@ -843,7 +840,7 @@ enum OGLVertexAttributeID #pragma mark - @implementation DisplayView -@synthesize cdsController; +@synthesize inputManager; @synthesize isHudEnabled; @synthesize isHudEditingModeEnabled; @@ -884,7 +881,7 @@ enum OGLVertexAttributeID glTexBackSize = NSMakeSize(w, h); vtxBufferOffset = 0; - cdsController = nil; + inputManager = nil; return self; } @@ -899,7 +896,7 @@ enum OGLVertexAttributeID free(glTexBack); glTexBack = NULL; - [self setCdsController:nil]; + [self setInputManager:nil]; [context clearDrawable]; [context release]; @@ -1309,33 +1306,60 @@ enum OGLVertexAttributeID return touchLoc; } +#pragma mark InputHIDManagerTarget Protocol +- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue +{ + BOOL isHandled = NO; + std::string inputStr; + DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; + + InputAttributesList inputList = InputManagerEncodeHIDQueue(hidQueue); + + const size_t inputCount = inputList.size(); + + for (unsigned int i = 0; i < inputCount; i++) + { + const InputAttributes &inputAttr = inputList[i]; + + if (inputAttr.inputState == INPUT_ATTRIBUTE_STATE_ON) + { + inputStr = inputAttr.deviceName + ":" + inputAttr.elementName; + break; + } + } + + if (!inputStr.empty()) + { + [[windowController emuControl] setStatusText:[NSString stringWithCString:inputStr.c_str() encoding:NSUTF8StringEncoding]]; + } + + CommandAttributesList cmdList = [inputManager generateCommandListUsingInputList:&inputList]; + + if (cmdList.empty()) + { + return isHandled; + } + + [inputManager dispatchCommandList:&cmdList]; + + isHandled = YES; + return isHandled; +} + - (BOOL) handleKeyPress:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed { BOOL isHandled = NO; DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; - if (self.cdsController == nil) - { - return isHandled; - } - - NSString *elementName = [NSString stringWithFormat:@"%d", [theEvent keyCode]]; - NSString *elementCode = elementName; - NSDictionary *inputAttributes = [NSDictionary dictionaryWithObjectsAndKeys: - @"NSEventKeyboard", @"deviceCode", - @"Keyboard", @"deviceName", - elementCode, @"elementCode", - elementName, @"elementName", - [NSNumber numberWithBool:keyPressed], @"on", - nil]; + const InputAttributes inputAttr = InputManagerEncodeKeyboardInput([theEvent keyCode], keyPressed); if (keyPressed && [theEvent window] != nil) { - [[windowController emuControl] setStatusText:[NSString stringWithFormat:@"Keyboard:%i", [theEvent keyCode]]]; + std::string inputStr = inputAttr.deviceName + ":" + inputAttr.elementName; + [[windowController emuControl] setStatusText:[NSString stringWithCString:inputStr.c_str() encoding:NSUTF8StringEncoding]]; } - isHandled = [self.cdsController setStateWithInput:inputAttributes]; - + isHandled = [inputManager dispatchCommandUsingInputAttributes:&inputAttr]; return isHandled; } @@ -1345,7 +1369,7 @@ enum OGLVertexAttributeID DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; const NSInteger displayModeID = [windowController displayMode]; - if (self.cdsController == nil || (displayModeID != DS_DISPLAY_TYPE_TOUCH && displayModeID != DS_DISPLAY_TYPE_COMBO)) + if (displayModeID != DS_DISPLAY_TYPE_TOUCH && displayModeID != DS_DISPLAY_TYPE_COMBO) { return isHandled; } @@ -1354,44 +1378,18 @@ enum OGLVertexAttributeID // and finally to DS touchscreen coordinates. NSPoint touchLoc = [self dsPointFromEvent:theEvent]; - NSString *elementCode = [NSString stringWithFormat:@"%li", (long)[theEvent buttonNumber]]; - NSString *elementName = [NSString stringWithFormat:@"Button %li", (long)[theEvent buttonNumber]]; - - switch ([theEvent buttonNumber]) - { - case kCGMouseButtonLeft: - elementName = @"Primary Button"; - break; - - case kCGMouseButtonRight: - elementName = @"Secondary Button"; - break; - - case kCGMouseButtonCenter: - elementName = @"Center Button"; - break; - - default: - break; - } - - NSDictionary *inputAttributes = [NSDictionary dictionaryWithObjectsAndKeys: - @"NSEventMouse", @"deviceCode", - @"Mouse", @"deviceName", - elementCode, @"elementCode", - elementName, @"elementName", - [NSNumber numberWithBool:buttonPressed], @"on", - [NSNumber numberWithFloat:touchLoc.x], @"pointX", - [NSNumber numberWithFloat:touchLoc.y], @"pointY", - nil]; + const InputAttributes inputAttr = InputManagerEncodeMouseButtonInput([theEvent buttonNumber], touchLoc, buttonPressed); if (buttonPressed && [theEvent window] != nil) { - [[windowController emuControl] setStatusText:[NSString stringWithFormat:@"Mouse:%li X:%li Y:%li", (long)[theEvent buttonNumber], (long)(touchLoc.x), (long)(touchLoc.y)]]; + char inputCoordBuf[256] = {0}; + snprintf(inputCoordBuf, 256, " X:%i Y:%i", (int)inputAttr.floatValue[0], (int)inputAttr.floatValue[1]); + + std::string inputStr = inputAttr.deviceName + ":" + inputAttr.elementName + std::string(inputCoordBuf); + [[windowController emuControl] setStatusText:[NSString stringWithCString:inputStr.c_str() encoding:NSUTF8StringEncoding]]; } - isHandled = [self.cdsController setStateWithInput:inputAttributes]; - + isHandled = [inputManager dispatchCommandUsingInputAttributes:&inputAttr]; return isHandled; } diff --git a/desmume/src/cocoa/userinterface/EmuControllerDelegate.h b/desmume/src/cocoa/userinterface/EmuControllerDelegate.h index 2898c371e..2fb48b03b 100644 --- a/desmume/src/cocoa/userinterface/EmuControllerDelegate.h +++ b/desmume/src/cocoa/userinterface/EmuControllerDelegate.h @@ -18,6 +18,7 @@ #import #include +@class InputManager; @class CocoaDSRom; @class CocoaDSFirmware; @class CocoaDSOutput; @@ -29,6 +30,8 @@ @interface EmuControllerDelegate : NSObject { + InputManager *inputManager; + CocoaDSRom *currentRom; CocoaDSFirmware *cdsFirmware; CocoaDSSpeaker *cdsSpeaker; @@ -78,6 +81,8 @@ OSSpinLock spinlockSpeaker; } +@property (readonly) IBOutlet InputManager *inputManager; + @property (assign) CocoaDSRom *currentRom; // Don't rely on autorelease since the emulator doesn't support concurrent unloading @property (retain) CocoaDSFirmware *cdsFirmware; @property (retain) CocoaDSSpeaker *cdsSpeaker; @@ -144,15 +149,12 @@ - (IBAction) importRomSave:(id)sender; - (IBAction) exportRomSave:(id)sender; -// Edit Menu -- (IBAction) copy:(id)sender; - // Emulation Menu -- (IBAction) speedLimitDisable:(id)sender; +- (IBAction) toggleSpeedLimiter:(id)sender; - (IBAction) toggleAutoFrameSkip:(id)sender; -- (IBAction) cheatsDisable:(id)sender; -- (IBAction) executeCoreToggle:(id)sender; -- (IBAction) resetCore:(id)sender; +- (IBAction) toggleCheats:(id)sender; +- (IBAction) toggleExecutePause:(id)sender; +- (IBAction) reset:(id)sender; - (IBAction) changeRomSaveType:(id)sender; // View Menu @@ -191,6 +193,21 @@ - (IBAction) closeSheet:(id)sender; +- (void) cmdUpdateDSController:(NSValue *)cmdAttrValue; + +- (void) cmdLoadEmuSaveStateSlot:(NSValue *)cmdAttrValue; +- (void) cmdSaveEmuSaveStateSlot:(NSValue *)cmdAttrValue; + +- (void) cmdCopyScreen:(NSValue *)cmdAttrValue; + +- (void) cmdToggleSpeedScalar:(NSValue *)cmdAttrValue; +- (void) cmdToggleSpeedLimiter:(NSValue *)cmdAttrValue; +- (void) cmdToggleAutoFrameSkip:(NSValue *)cmdAttrValue; +- (void) cmdToggleCheats:(NSValue *)cmdAttrValue; +- (void) cmdToggleExecutePause:(NSValue *)cmdAttrValue; +- (void) cmdReset:(NSValue *)cmdAttrValue; +- (void) cmdToggleGPUState:(NSValue *)cmdAttrValue; + - (BOOL) handleLoadRom:(NSURL *)fileURL; - (BOOL) handleUnloadRom:(NSInteger)reasonID romToLoad:(NSURL *)romURL; - (BOOL) loadRom:(NSURL *)romURL; diff --git a/desmume/src/cocoa/userinterface/EmuControllerDelegate.mm b/desmume/src/cocoa/userinterface/EmuControllerDelegate.mm index 466e21747..aa9018659 100644 --- a/desmume/src/cocoa/userinterface/EmuControllerDelegate.mm +++ b/desmume/src/cocoa/userinterface/EmuControllerDelegate.mm @@ -17,6 +17,7 @@ #import "EmuControllerDelegate.h" #import "DisplayWindowController.h" +#import "InputManager.h" #import "cheatWindowDelegate.h" #import "cocoa_globals.h" @@ -25,12 +26,15 @@ #import "cocoa_file.h" #import "cocoa_firmware.h" #import "cocoa_GPU.h" +#import "cocoa_input.h" #import "cocoa_output.h" #import "cocoa_rom.h" @implementation EmuControllerDelegate +@synthesize inputManager; + @synthesize currentRom; @dynamic cdsFirmware; @dynamic cdsSpeaker; @@ -414,10 +418,9 @@ - (IBAction) newDisplayWindow:(id)sender { - CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; DisplayWindowController *newWindowController = [[DisplayWindowController alloc] initWithWindowNibName:@"DisplayWindow" emuControlDelegate:self]; [windowList addObject:newWindowController]; - [newWindowController setCdsController:[cdsCore cdsController]]; + [[newWindowController view] setInputManager:[self inputManager]]; [self updateAllWindowTitles]; [newWindowController showWindow:self]; @@ -636,69 +639,14 @@ - (IBAction) loadEmuSaveStateSlot:(id)sender { - NSString *saveStatePath = [[CocoaDSFile saveStateURL] path]; - if (saveStatePath == nil) - { - // Should throw an error message here... - return; - } - const NSInteger slotNumber = [CocoaDSUtil getIBActionSenderTag:sender]; - if (slotNumber < 0 || slotNumber > MAX_SAVESTATE_SLOTS) - { - return; - } - - NSURL *currentRomURL = [[self currentRom] fileURL]; - NSString *fileName = [CocoaDSFile saveSlotFileName:currentRomURL slotNumber:(NSUInteger)(slotNumber + 1)]; - if (fileName == nil) - { - return; - } - - [self pauseCore]; - - const BOOL isStateLoaded = [CocoaDSFile loadState:[NSURL fileURLWithPath:[saveStatePath stringByAppendingPathComponent:fileName]]]; - [self setStatusText:(isStateLoaded) ? NSSTRING_STATUS_SAVESTATE_LOADED : NSSTRING_STATUS_SAVESTATE_LOADING_FAILED]; - - [self restoreCoreState]; + [inputManager dispatchCommandUsingIBAction:_cmd tag:slotNumber]; } - (IBAction) saveEmuSaveStateSlot:(id)sender { - NSString *saveStatePath = [[CocoaDSFile saveStateURL] path]; - if (saveStatePath == nil) - { - [self setStatusText:NSSTRING_STATUS_CANNOT_GENERATE_SAVE_PATH]; - return; - } - - const BOOL isDirectoryCreated = [CocoaDSFile createUserAppSupportDirectory:@"States"]; - if (!isDirectoryCreated) - { - [self setStatusText:NSSTRING_STATUS_CANNOT_CREATE_SAVE_DIRECTORY]; - return; - } - const NSInteger slotNumber = [CocoaDSUtil getIBActionSenderTag:sender]; - if (slotNumber < 0 || slotNumber > MAX_SAVESTATE_SLOTS) - { - return; - } - - NSURL *currentRomURL = [[self currentRom] fileURL]; - NSString *fileName = [CocoaDSFile saveSlotFileName:currentRomURL slotNumber:(NSUInteger)(slotNumber + 1)]; - if (fileName == nil) - { - return; - } - - [self pauseCore]; - - const BOOL isStateSaved = [CocoaDSFile saveState:[NSURL fileURLWithPath:[saveStatePath stringByAppendingPathComponent:fileName]]]; - [self setStatusText:(isStateSaved) ? NSSTRING_STATUS_SAVESTATE_SAVED : NSSTRING_STATUS_SAVESTATE_SAVING_FAILED]; - - [self restoreCoreState]; + [inputManager dispatchCommandUsingIBAction:_cmd tag:slotNumber]; } - (IBAction) importRomSave:(id)sender @@ -758,93 +706,24 @@ [self restoreCoreState]; } -- (IBAction) copy:(id)sender +- (IBAction) toggleExecutePause:(id)sender { - [mainWindow copy:sender]; + [inputManager dispatchCommandUsingIBAction:_cmd tag:0]; } -- (IBAction) executeCoreToggle:(id)sender +- (IBAction) reset:(id)sender { - CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; - - if ([cdsCore coreState] == CORESTATE_PAUSE) - { - if ([self currentRom] != nil) - { - [self executeCore]; - } - } - else - { - [self pauseCore]; - } + [inputManager dispatchCommandUsingIBAction:_cmd tag:0]; } -- (IBAction) resetCore:(id)sender +- (IBAction) toggleSpeedLimiter:(id)sender { - if ([self currentRom] == nil) - { - return; - } - - CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; - - [self setStatusText:NSSTRING_STATUS_EMULATOR_RESETTING]; - [self setIsWorking:YES]; - - for (DisplayWindowController *windowController in windowList) - { - [[windowController window] displayIfNeeded]; - } - - [cdsCore reset]; - if ([cdsCore coreState] == CORESTATE_PAUSE) - { - for (DisplayWindowController *windowController in windowList) - { - [[windowController view] clearToWhite]; - } - } - - [self setStatusText:NSSTRING_STATUS_EMULATOR_RESET]; - [self setIsWorking:NO]; - - for (DisplayWindowController *windowController in windowList) - { - [[windowController window] displayIfNeeded]; - } -} - -- (IBAction) speedLimitDisable:(id)sender -{ - CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; - - if ([cdsCore isSpeedLimitEnabled]) - { - [cdsCore setIsSpeedLimitEnabled:NO]; - [self setStatusText:NSSTRING_STATUS_SPEED_LIMIT_DISABLED]; - } - else - { - [cdsCore setIsSpeedLimitEnabled:YES]; - [self setStatusText:NSSTRING_STATUS_SPEED_LIMIT_ENABLED]; - } + [inputManager dispatchCommandUsingIBAction:_cmd tag:0]; } - (IBAction) toggleAutoFrameSkip:(id)sender { - CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; - - if ([cdsCore isFrameSkipEnabled]) - { - [cdsCore setIsFrameSkipEnabled:NO]; - [self setStatusText:NSSTRING_STATUS_AUTO_FRAME_SKIP_DISABLED]; - } - else - { - [cdsCore setIsFrameSkipEnabled:YES]; - [self setStatusText:NSSTRING_STATUS_AUTO_FRAME_SKIP_ENABLED]; - } + [inputManager dispatchCommandUsingIBAction:_cmd tag:0]; } - (IBAction) toggleKeepMinDisplaySizeAtNormal:(id)sender @@ -874,11 +753,8 @@ - (IBAction) toggleGPUState:(id)sender { - CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; const NSInteger bitNumber = [CocoaDSUtil getIBActionSenderTag:sender]; - const UInt32 flagBit = [cdsCore.cdsGPU gpuStateFlags] ^ (1 << bitNumber); - - [cdsCore.cdsGPU setGpuStateFlags:flagBit]; + [inputManager dispatchCommandUsingIBAction:_cmd tag:bitNumber]; } - (IBAction) changeRomSaveType:(id)sender @@ -890,20 +766,9 @@ [cdsCore changeRomSaveType:saveTypeID]; } -- (IBAction) cheatsDisable:(id)sender +- (IBAction) toggleCheats:(id)sender { - CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; - - if ([cdsCore isCheatingEnabled]) - { - [cdsCore setIsCheatingEnabled:NO]; - [self setStatusText:NSSTRING_STATUS_CHEATS_DISABLED]; - } - else - { - [cdsCore setIsCheatingEnabled:YES]; - [self setStatusText:NSSTRING_STATUS_CHEATS_ENABLED]; - } + [inputManager dispatchCommandUsingIBAction:_cmd tag:0]; } - (IBAction) changeCoreSpeed:(id)sender @@ -1114,6 +979,226 @@ #pragma mark Class Methods +- (void) cmdUpdateDSController:(NSValue *)cmdAttrValue +{ + CommandAttributes cmdAttr; + [cmdAttrValue getValue:&cmdAttr]; + + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + NSUInteger controlID = (NSUInteger)cmdAttr.commandID; + BOOL theState = (cmdAttr.inputState == INPUT_ATTRIBUTE_STATE_ON) ? YES : NO; + + if (controlID == DSControllerState_Touch) + { + NSPoint touchLoc = NSMakePoint(cmdAttr.floatValue[0], cmdAttr.floatValue[1]); + [[cdsCore cdsController] setTouchState:theState location:touchLoc]; + } + else + { + [[cdsCore cdsController] setControllerState:theState controlID:controlID]; + } +} + +- (void) cmdLoadEmuSaveStateSlot:(NSValue *)cmdAttrValue +{ + CommandAttributes cmdAttr; + [cmdAttrValue getValue:&cmdAttr]; + + NSString *saveStatePath = [[CocoaDSFile saveStateURL] path]; + if (saveStatePath == nil) + { + // Should throw an error message here... + return; + } + + const NSInteger slotNumber = cmdAttr.integerValue[0]; + if (slotNumber < 0 || slotNumber > MAX_SAVESTATE_SLOTS) + { + return; + } + + NSURL *currentRomURL = [[self currentRom] fileURL]; + NSString *fileName = [CocoaDSFile saveSlotFileName:currentRomURL slotNumber:(NSUInteger)(slotNumber + 1)]; + if (fileName == nil) + { + return; + } + + [self pauseCore]; + + const BOOL isStateLoaded = [CocoaDSFile loadState:[NSURL fileURLWithPath:[saveStatePath stringByAppendingPathComponent:fileName]]]; + [self setStatusText:(isStateLoaded) ? NSSTRING_STATUS_SAVESTATE_LOADED : NSSTRING_STATUS_SAVESTATE_LOADING_FAILED]; + + [self restoreCoreState]; +} + +- (void) cmdSaveEmuSaveStateSlot:(NSValue *)cmdAttrValue +{ + CommandAttributes cmdAttr; + [cmdAttrValue getValue:&cmdAttr]; + + NSString *saveStatePath = [[CocoaDSFile saveStateURL] path]; + if (saveStatePath == nil) + { + [self setStatusText:NSSTRING_STATUS_CANNOT_GENERATE_SAVE_PATH]; + return; + } + + const BOOL isDirectoryCreated = [CocoaDSFile createUserAppSupportDirectory:@"States"]; + if (!isDirectoryCreated) + { + [self setStatusText:NSSTRING_STATUS_CANNOT_CREATE_SAVE_DIRECTORY]; + return; + } + + const NSInteger slotNumber = cmdAttr.integerValue[0]; + if (slotNumber < 0 || slotNumber > MAX_SAVESTATE_SLOTS) + { + return; + } + + NSURL *currentRomURL = [[self currentRom] fileURL]; + NSString *fileName = [CocoaDSFile saveSlotFileName:currentRomURL slotNumber:(NSUInteger)(slotNumber + 1)]; + if (fileName == nil) + { + return; + } + + [self pauseCore]; + + const BOOL isStateSaved = [CocoaDSFile saveState:[NSURL fileURLWithPath:[saveStatePath stringByAppendingPathComponent:fileName]]]; + [self setStatusText:(isStateSaved) ? NSSTRING_STATUS_SAVESTATE_SAVED : NSSTRING_STATUS_SAVESTATE_SAVING_FAILED]; + + [self restoreCoreState]; +} + +- (void) cmdCopyScreen:(NSValue *)cmdAttrValue +{ + [mainWindow copy:nil]; +} + +- (void) cmdToggleSpeedScalar:(NSValue *)cmdAttrValue +{ + CommandAttributes cmdAttr; + [cmdAttrValue getValue:&cmdAttr]; + CGFloat speedScalar = cmdAttr.floatValue[0]; + + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + [cdsCore setSpeedScalar:speedScalar]; +} + +- (void) cmdToggleSpeedLimiter:(NSValue *)cmdAttrValue +{ + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + + if ([cdsCore isSpeedLimitEnabled]) + { + [cdsCore setIsSpeedLimitEnabled:NO]; + [self setStatusText:NSSTRING_STATUS_SPEED_LIMIT_DISABLED]; + } + else + { + [cdsCore setIsSpeedLimitEnabled:YES]; + [self setStatusText:NSSTRING_STATUS_SPEED_LIMIT_ENABLED]; + } +} + +- (void) cmdToggleAutoFrameSkip:(NSValue *)cmdAttrValue +{ + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + + if ([cdsCore isFrameSkipEnabled]) + { + [cdsCore setIsFrameSkipEnabled:NO]; + [self setStatusText:NSSTRING_STATUS_AUTO_FRAME_SKIP_DISABLED]; + } + else + { + [cdsCore setIsFrameSkipEnabled:YES]; + [self setStatusText:NSSTRING_STATUS_AUTO_FRAME_SKIP_ENABLED]; + } +} + +- (void) cmdToggleCheats:(NSValue *)cmdAttrValue +{ + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + + if ([cdsCore isCheatingEnabled]) + { + [cdsCore setIsCheatingEnabled:NO]; + [self setStatusText:NSSTRING_STATUS_CHEATS_DISABLED]; + } + else + { + [cdsCore setIsCheatingEnabled:YES]; + [self setStatusText:NSSTRING_STATUS_CHEATS_ENABLED]; + } +} + +- (void) cmdToggleExecutePause:(NSValue *)cmdAttrValue +{ + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + + if ([cdsCore coreState] == CORESTATE_PAUSE) + { + if ([self currentRom] != nil) + { + [self executeCore]; + } + } + else + { + [self pauseCore]; + } +} + +- (void) cmdReset:(NSValue *)cmdAttrValue +{ + if ([self currentRom] == nil) + { + return; + } + + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + + [self setStatusText:NSSTRING_STATUS_EMULATOR_RESETTING]; + [self setIsWorking:YES]; + + for (DisplayWindowController *windowController in windowList) + { + [[windowController window] displayIfNeeded]; + } + + [cdsCore reset]; + if ([cdsCore coreState] == CORESTATE_PAUSE) + { + for (DisplayWindowController *windowController in windowList) + { + [[windowController view] clearToWhite]; + } + } + + [self setStatusText:NSSTRING_STATUS_EMULATOR_RESET]; + [self setIsWorking:NO]; + + for (DisplayWindowController *windowController in windowList) + { + [[windowController window] displayIfNeeded]; + } +} + +- (void) cmdToggleGPUState:(NSValue *)cmdAttrValue +{ + CommandAttributes cmdAttr; + [cmdAttrValue getValue:&cmdAttr]; + + CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + const NSInteger bitNumber = cmdAttr.integerValue[0]; + const UInt32 flagBit = [cdsCore.cdsGPU gpuStateFlags] ^ (1 << bitNumber); + + [cdsCore.cdsGPU setGpuStateFlags:flagBit]; +} + - (BOOL) handleLoadRom:(NSURL *)fileURL { BOOL result = NO; @@ -1635,7 +1720,7 @@ enable = NO; } } - else if (theAction == @selector(executeCoreToggle:)) + else if (theAction == @selector(toggleExecutePause:)) { if (![cdsCore masterExecute] || [self currentRom] == nil || @@ -1679,7 +1764,7 @@ enable = NO; } } - else if (theAction == @selector(resetCore:)) + else if (theAction == @selector(reset:)) { if ([self currentRom] == nil || [self isUserInterfaceBlockingExecution]) { @@ -1777,7 +1862,7 @@ } } } - else if (theAction == @selector(speedLimitDisable:)) + else if (theAction == @selector(toggleSpeedLimiter:)) { if ([(id)theItem isMemberOfClass:[NSMenuItem class]]) { diff --git a/desmume/src/cocoa/userinterface/InputManager.h b/desmume/src/cocoa/userinterface/InputManager.h new file mode 100644 index 000000000..7a59d48ec --- /dev/null +++ b/desmume/src/cocoa/userinterface/InputManager.h @@ -0,0 +1,176 @@ +/* + Copyright (C) 2013 DeSmuME team + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . + */ + +#import +#include +#include + +#include +#include +#include + +#define INPUT_HANDLER_MAX_ATTRIBUTE_VALUES 4 + +enum +{ + INPUT_ATTRIBUTE_STATE_OFF = 0, + INPUT_ATTRIBUTE_STATE_ON, + INPUT_ATTRIBUTE_STATE_MIXED +}; + +@class EmuControllerDelegate; +@class CocoaDSController; +@class InputManager; +@class InputHIDManager; + +@protocol InputHIDManagerTarget + +@required +- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue; + +@end + +typedef struct +{ + std::string deviceName; + std::string deviceCode; + std::string elementName; + std::string elementCode; + + NSInteger inputState; + + NSInteger integerValue[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; + CGFloat floatValue[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; + id object[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; +} InputAttributes; + +typedef struct +{ + SEL selector; + NSInteger commandID; + NSInteger inputState; + + NSInteger integerValue[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; + BOOL useIntegerInputValue[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; + + CGFloat floatValue[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; + BOOL useFloatInputValue[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; + + id object[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; + BOOL useObjectInputValue[INPUT_HANDLER_MAX_ATTRIBUTE_VALUES]; +} CommandAttributes; + +typedef std::vector InputAttributesList; +typedef std::vector CommandAttributesList; +typedef std::tr1::unordered_map CommandTagMap; // Key = Input key in deviceCode:elementCode format, Value = Command Tag +typedef std::tr1::unordered_map CommandAttributesMap; // Key = Command Tag, Value = CommandAttributes + +#pragma mark - +@interface InputHIDDevice : NSObject +{ + InputHIDManager *hidManager; + IOHIDDeviceRef hidDeviceRef; + IOHIDQueueRef hidQueueRef; + NSRunLoop *runLoop; + OSSpinLock spinlockRunLoop; +} + +@property (retain) InputHIDManager *hidManager; +@property (readonly) IOHIDDeviceRef hidDeviceRef; +@property (retain) NSRunLoop *runLoop; + +- (id) initWithDevice:(IOHIDDeviceRef)theDevice hidManager:(InputHIDManager *)theHIDManager; + +- (void) start; +- (void) stop; + +- (NSString *) manufacturerName; +- (NSString *) productName; +- (NSString *) serialNumber; + +@end + +BOOL GetOnStateFromHIDValueRef(IOHIDValueRef hidValueRef); +InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef, const char *altElementCode, const char *altElementName, NSNumber *altOnState); +InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef); +InputAttributesList InputListFromHatSwitchValue(IOHIDValueRef hidValueRef, bool useEightDirection); + +unsigned int ClearHIDQueue(const IOHIDQueueRef hidQueue); +void HandleQueueValueAvailableCallback(void *inContext, IOReturn inResult, void *inSender); + +#pragma mark - +@interface InputHIDManager : NSObject +{ + InputManager *inputManager; + IOHIDManagerRef hidManagerRef; + NSRunLoop *runLoop; + NSMutableSet *deviceList; + id target; + + OSSpinLock spinlockRunLoop; +} + +@property (retain) InputManager *inputManager; +@property (readonly) IOHIDManagerRef hidManagerRef; +@property (readonly) NSMutableSet *deviceList; +@property (assign) id target; +@property (retain) NSRunLoop *runLoop; + +- (id) initWithInputManager:(InputManager *)theInputManager; + +@end + +void HandleDeviceMatchingCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef); +void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef); + +#pragma mark - +@interface InputManager : NSObject +{ + EmuControllerDelegate *emuControl; + id hidInputTarget; + InputHIDManager *hidManager; + + CommandTagMap commandMap; + CommandAttributesMap commandMasterList; +} + +@property (assign) IBOutlet EmuControllerDelegate *emuControl; +@property (retain) id hidInputTarget; + +- (void) addMappingsUsingUserDefaults; +- (void) addMappingUsingDeviceInfoDictionary:(NSDictionary *)deviceDict commandTag:(const char *)commandTag; +- (void) addMappingUsingInputAttributes:(const InputAttributes *)inputAttr commandTag:(const char *)commandTag; +- (void) addMappingUsingInputList:(const InputAttributesList *)inputList commandTag:(const char *)commandTag; +- (void) addMappingForIBAction:(const SEL)theSelector commandTag:(const char *)commandTag; +- (void) addMappingUsingDeviceCode:(const char *)deviceCode elementCode:(const char *)elementCode commandTag:(const char *)commandTag; + +- (void) removeMappingUsingDeviceCode:(const char *)deviceCode elementCode:(const char *)elementCode; +- (void) removeAllMappingsOfCommandTag:(const char *)commandTag; + +- (CommandAttributesList) generateCommandListUsingInputList:(const InputAttributesList *)inputList; +- (void) dispatchCommandList:(const CommandAttributesList *)cmdList; +- (BOOL) dispatchCommandUsingInputAttributes:(const InputAttributes *)inputAttr; +- (BOOL) dispatchCommandUsingIBAction:(const SEL)theSelector tag:(const NSInteger)tagValue; + +- (void) writeUserDefaultsMappingUsingInputAttributes:(const InputAttributes *)inputAttr commandTag:(const char *)commandTag; + +InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue); +InputAttributes InputManagerEncodeKeyboardInput(const unsigned short keyCode, BOOL keyPressed); +InputAttributes InputManagerEncodeMouseButtonInput(const NSInteger buttonNumber, const NSPoint touchLoc, BOOL buttonPressed); +InputAttributes InputManagerEncodeIBAction(const SEL theSelector, const NSInteger tagValue); + +@end diff --git a/desmume/src/cocoa/userinterface/InputManager.mm b/desmume/src/cocoa/userinterface/InputManager.mm new file mode 100644 index 000000000..21189d840 --- /dev/null +++ b/desmume/src/cocoa/userinterface/InputManager.mm @@ -0,0 +1,1324 @@ +/* + Copyright (C) 2011 Roger Manuel + Copyright (C) 2012-2013 DeSmuME team + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . + */ + +#import "InputManager.h" +#import "EmuControllerDelegate.h" + +#import "cocoa_input.h" +#import "cocoa_util.h" + +/* + Get the symbols for UpdateSystemActivity(). + + For some reason, in Mac OS v10.5 and earlier, UpdateSystemActivity() is not + defined for 64-bit, even though it does work on 64-bit systems. So we're going + to copy the symbols from OSServices/Power.h so that we can use them. This + solution is better than making an absolute path to the Power.h file, since + we can't assume that the header file will always be in the same location. + + Note that this isn't a problem on 32-bit, or if the target SDK is Mac OS v10.6 + or later. + */ + +#if !__LP64__ || MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 + +#include + +#else + +#ifdef __cplusplus +extern "C" +{ +#endif + + extern OSErr UpdateSystemActivity(UInt8 activity); + + enum + { + OverallAct = 0, + UsrActivity = 1, + NetActivity = 2, + HDActivity = 3, + IdleActivity = 4 + }; + +#ifdef __cplusplus +} +#endif + +#endif // !__LP64__ || MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 + +#pragma mark - +@implementation InputHIDDevice + +@synthesize hidManager; +@synthesize hidDeviceRef; +@dynamic runLoop; + +static NSDictionary *hidUsageTable = nil; + +- (id) initWithDevice:(IOHIDDeviceRef)theDevice hidManager:(InputHIDManager *)theHIDManager +{ + self = [super init]; + if(self == nil) + { + return self; + } + + if (hidUsageTable == nil) + { + hidUsageTable = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HID_usage_strings" ofType:@"plist"]]; + } + + hidManager = [theHIDManager retain]; + hidDeviceRef = theDevice; + + hidQueueRef = IOHIDQueueCreate(kCFAllocatorDefault, hidDeviceRef, 10, kIOHIDOptionsTypeNone); + if (hidQueueRef == NULL) + { + [self release]; + return nil; + } + + CFArrayRef elementArray = IOHIDDeviceCopyMatchingElements(hidDeviceRef, NULL, kIOHIDOptionsTypeNone); + NSEnumerator *enumerator = [(NSArray *)elementArray objectEnumerator]; + IOHIDElementRef hidElement = NULL; + + while ((hidElement = (IOHIDElementRef)[enumerator nextObject])) + { + IOHIDQueueAddElement(hidQueueRef, hidElement); + } + + CFRelease(elementArray); + + spinlockRunLoop = OS_SPINLOCK_INIT; + [self setRunLoop:[NSRunLoop currentRunLoop]]; + + return self; +} + +- (void)dealloc +{ + [self stop]; + [self setRunLoop:nil]; + [self setHidManager:nil]; + + if (hidQueueRef != NULL) + { + CFRelease(hidQueueRef); + hidQueueRef = NULL; + } + + [super dealloc]; +} + +- (void) setRunLoop:(NSRunLoop *)theRunLoop +{ + OSSpinLockLock(&spinlockRunLoop); + + if (theRunLoop == runLoop) + { + OSSpinLockUnlock(&spinlockRunLoop); + return; + } + + if (theRunLoop == nil) + { + IOHIDQueueRegisterValueAvailableCallback(hidQueueRef, NULL, NULL); + IOHIDQueueUnscheduleFromRunLoop(hidQueueRef, [runLoop getCFRunLoop], kCFRunLoopDefaultMode); + } + else + { + [theRunLoop retain]; + IOHIDQueueScheduleWithRunLoop(hidQueueRef, [theRunLoop getCFRunLoop], kCFRunLoopDefaultMode); + IOHIDQueueRegisterValueAvailableCallback(hidQueueRef, HandleQueueValueAvailableCallback, [self hidManager]); + } + + [runLoop release]; + runLoop = theRunLoop; + + OSSpinLockUnlock(&spinlockRunLoop); +} + +- (NSRunLoop *) runLoop +{ + OSSpinLockLock(&spinlockRunLoop); + NSRunLoop *theRunLoop = runLoop; + OSSpinLockUnlock(&spinlockRunLoop); + + return theRunLoop; +} + +- (void) start +{ + IOHIDQueueStart(hidQueueRef); +} + +- (void) stop +{ + IOHIDQueueStop(hidQueueRef); +} + +- (NSString *) manufacturerName +{ + return (NSString *)IOHIDDeviceGetProperty([self hidDeviceRef], CFSTR(kIOHIDManufacturerKey)); +} + +- (NSString *) productName +{ + return (NSString *)IOHIDDeviceGetProperty([self hidDeviceRef], CFSTR(kIOHIDProductKey)); +} + +- (NSString *) serialNumber +{ + return (NSString *)IOHIDDeviceGetProperty([self hidDeviceRef], CFSTR(kIOHIDSerialNumberKey)); +} + +@end + +/******************************************************************************************** + InputAttributesOfHIDValue() + + Parses an IOHIDValueRef into an input attributes struct. + + Takes: + hidValueRef - The IOHIDValueRef to parse. + altElementCode - An NSString that overrides the default element code. + altElementName - An NSString that overrides the default element name. + altOnState - An NSNumber that overrides the default on state. + + Returns: + An InputAttributes struct with the parsed input attributes. + + Details: + None. + ********************************************************************************************/ +InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef, const char *altElementCode, const char *altElementName, NSNumber *altOnState) +{ + InputAttributes inputAttr; + + if (hidValueRef == NULL) + { + return inputAttr; + } + + char deviceCodeBuf[256] = {0}; + char deviceNameBuf[256] = {0}; + char elementCodeBuf[256] = {0}; + char elementNameBuf[256] = {0}; + + IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef); + NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef); + NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef); + + if (altElementCode == NULL) + { + snprintf(elementCodeBuf, 256, "0x%04lX/0x%04lX", (long)elementUsagePage, (long)elementUsage); + } + else + { + strncpy(elementCodeBuf, altElementCode, 256); + } + + if (altElementName == NULL) + { + CFStringRef cfElementName = IOHIDElementGetName(hidElementRef); + if (cfElementName == nil) + { + if (elementUsagePage == kHIDPage_Button) + { + snprintf(elementNameBuf, 256, "Button %li", (long)elementUsage); + } + else if (elementUsagePage == kHIDPage_VendorDefinedStart) + { + snprintf(elementNameBuf, 256, "VendorDefined %li", (long)elementUsage); + } + else + { + NSDictionary *elementUsagePageDict = (NSDictionary *)[hidUsageTable valueForKey:[NSString stringWithFormat:@"0x%04lX", (long)elementUsagePage]]; + + NSString *elementNameLookup = (NSString *)[elementUsagePageDict valueForKey:[NSString stringWithFormat:@"0x%04lX", (long)elementUsage]]; + if (elementNameLookup != nil) + { + strncpy(elementNameBuf, [elementNameLookup cStringUsingEncoding:NSUTF8StringEncoding], 256); + } + } + } + else + { + CFStringGetCString(cfElementName, elementNameBuf, 256, kCFStringEncodingUTF8); + } + } + else + { + strncpy(elementNameBuf, altElementName, 256); + } + + IOHIDDeviceRef hidDeviceRef = IOHIDElementGetDevice(hidElementRef); + + CFNumberRef cfVendorIDNumber = (CFNumberRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDVendorIDKey)); + SInt32 vendorID = 0; + CFNumberGetValue(cfVendorIDNumber, kCFNumberSInt32Type, &vendorID); + + CFNumberRef cfProductIDNumber = (CFNumberRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDProductIDKey)); + SInt32 productID = 0; + CFNumberGetValue(cfProductIDNumber, kCFNumberSInt32Type, &productID); + + CFStringRef cfDeviceCode = (CFStringRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDSerialNumberKey)); + if (cfDeviceCode == nil) + { + CFNumberRef cfLocationIDNumber = (CFNumberRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDLocationIDKey)); + SInt32 locationID = 0; + CFNumberGetValue(cfLocationIDNumber, kCFNumberSInt32Type, &locationID); + + snprintf(deviceCodeBuf, 256, "%d/%d/0x%08X", (int)vendorID, (int)productID, (unsigned int)locationID); + } + else + { + char cfDeviceCodeBuf[256] = {0}; + CFStringGetCString(cfDeviceCode, cfDeviceCodeBuf, 256, kCFStringEncodingUTF8); + snprintf(deviceCodeBuf, 256, "%d/%d/%s", (int)vendorID, (int)productID, cfDeviceCodeBuf); + } + + CFStringRef cfDeviceName = (CFStringRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDProductKey)); + if (cfDeviceName == nil) + { + strncpy(deviceNameBuf, deviceCodeBuf, 256); + } + else + { + CFStringGetCString(cfDeviceName, deviceNameBuf, 256, kCFStringEncodingUTF8); + } + + BOOL onState = (altOnState == nil) ? GetOnStateFromHIDValueRef(hidValueRef) : [altOnState boolValue]; + CFIndex logicalValue = IOHIDValueGetIntegerValue(hidValueRef); + + inputAttr.deviceCode = std::string(deviceCodeBuf); + inputAttr.deviceName = std::string(deviceNameBuf); + inputAttr.elementCode = std::string(elementCodeBuf); + inputAttr.elementName = std::string(elementNameBuf); + inputAttr.inputState = (onState) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF; + inputAttr.integerValue[0] = (NSInteger)logicalValue; + inputAttr.floatValue[0] = (CGFloat)logicalValue; + + return inputAttr; +} + +InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef) +{ + InputAttributesList inputList; + + if (hidValueRef == NULL) + { + return inputList; + } + + IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef); + NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef); + NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef); + + // IOHIDValueGetIntegerValue() will crash if the value length is too large. + // Do a bounds check here to prevent crashing. This workaround makes the PS3 + // controller usable, since it returns a length of 39 on some elements. + if(IOHIDValueGetLength(hidValueRef) > 2) + { + return inputList; + } + + NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef); + NSInteger logicalMin = IOHIDElementGetLogicalMin(hidElementRef); + NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef); + + inputList.resize(2); + + if (logicalMin == 0 && logicalMax == 1) + { + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, NULL, NULL, nil)); + } + else + { + NSInteger lowerThreshold = ((logicalMax - logicalMin) / 3) + logicalMin; + NSInteger upperThreshold = (((logicalMax - logicalMin) * 2) / 3) + logicalMin; + NSNumber *onState = [NSNumber numberWithBool:YES]; + NSNumber *offState = [NSNumber numberWithBool:NO]; + + char elementCodeLowerThresholdBuf[256] = {0}; + char elementCodeUpperThresholdBuf[256] = {0}; + snprintf(elementCodeLowerThresholdBuf, 256, "0x%04lX/0x%04lX/LowerThreshold", (long)elementUsagePage, (long)elementUsage); + snprintf(elementCodeUpperThresholdBuf, 256, "0x%04lX/0x%04lX/UpperThreshold", (long)elementUsagePage, (long)elementUsage); + + if (logicalValue <= lowerThreshold) + { + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeLowerThresholdBuf, NULL, onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeUpperThresholdBuf, NULL, offState)); + } + else if (logicalValue >= upperThreshold) + { + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeLowerThresholdBuf, NULL, offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeUpperThresholdBuf, NULL, onState)); + } + else + { + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeLowerThresholdBuf, NULL, offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeUpperThresholdBuf, NULL, onState)); + } + } + + return inputList; +} + +InputAttributesList InputListFromHatSwitchValue(IOHIDValueRef hidValueRef, bool useEightDirection) +{ + InputAttributesList inputList; + + if (hidValueRef == NULL) + { + return inputList; + } + + IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef); + NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef); + NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef); + + if (elementUsage != kHIDUsage_GD_Hatswitch) + { + return inputList; + } + + inputList.resize(8); + NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef); + NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef); + + NSNumber *onState = [NSNumber numberWithBool:YES]; + NSNumber *offState = [NSNumber numberWithBool:NO]; + + char elementCodeFourWay[4][256]; + for (unsigned int i = 0; i < 4; i++) + { + snprintf(elementCodeFourWay[i], 256, "0x%04lX/0x%04lX/%d-FourDirection", (long)elementUsagePage, (long)elementUsage, i); + } + + const char *elementNameFourWay[4] = { + "Hatswitch - Up", + "Hatswitch - Right", + "Hatswitch - Down", + "Hatswitch - Left" }; + + char elementCodeEightWay[8][256]; + for (unsigned int i = 0; i < 8; i++) + { + snprintf(elementCodeEightWay[i], 256, "0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, i); + } + + const char *elementNameEightWay[8] = { + "Hatswitch - Up", + "Hatswitch - Up/Right", + "Hatswitch - Right", + "Hatswitch - Down/Right", + "Hatswitch - Down", + "Hatswitch - Down/Left", + "Hatswitch - Left", + "Hatswitch - Up/Left" }; + + if (logicalMax == 3) + { + for (unsigned int i = 0; i <= (unsigned int)logicalMax; i++) + { + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeFourWay[i], elementNameFourWay[i], (i == (unsigned int)logicalValue) ? onState : offState)); + } + } + else if (logicalMax == 7) + { + if (useEightDirection) + { + for (unsigned int i = 0; i <= (unsigned int)logicalMax; i++) + { + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[i], elementNameEightWay[i], (i == (unsigned int)logicalValue) ? onState : offState)); + } + } + else + { + switch (logicalValue) + { + case 0: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], offState)); + break; + + case 1: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], offState)); + break; + + case 2: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], offState)); + break; + + case 3: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], offState)); + break; + + case 4: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], offState)); + break; + + case 5: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], onState)); + break; + + case 6: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], onState)); + break; + + case 7: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], onState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], onState)); + break; + + default: + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], offState)); + inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], offState)); + break; + } + } + } + + return inputList; +} + +BOOL GetOnStateFromHIDValueRef(IOHIDValueRef hidValueRef) +{ + BOOL onState = NO; + + if (hidValueRef == nil) + { + return onState; + } + + IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef); + NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef); + NSInteger logicalMin = IOHIDElementGetLogicalMin(hidElementRef); + NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef); + NSInteger lowerThreshold = ((logicalMax - logicalMin) / 4) + logicalMin; + NSInteger upperThreshold = (((logicalMax - logicalMin) * 3) / 4) + logicalMin; + + NSInteger elementType = IOHIDElementGetType(hidElementRef); + switch (elementType) + { + case kIOHIDElementTypeInput_Misc: + { + if (logicalMin == 0 && logicalMax == 1) + { + if (logicalValue == 1) + { + onState = YES; + } + } + else + { + if (logicalValue <= lowerThreshold || logicalValue >= upperThreshold) + { + onState = YES; + } + } + break; + } + + case kIOHIDElementTypeInput_Button: + { + if (logicalValue == 1) + { + onState = YES; + } + break; + } + + case kIOHIDElementTypeInput_Axis: + { + if (logicalMin == 0 && logicalMax == 1) + { + if (logicalValue == 1) + { + onState = YES; + } + } + else + { + if (logicalValue <= lowerThreshold || logicalValue >= upperThreshold) + { + onState = YES; + } + } + break; + } + + default: + break; + } + + return onState; +} + +unsigned int ClearHIDQueue(const IOHIDQueueRef hidQueue) +{ + unsigned int hidInputClearCount = 0; + + if (hidQueue == nil) + { + return hidInputClearCount; + } + + do + { + IOHIDValueRef hidValueRef = IOHIDQueueCopyNextValueWithTimeout(hidQueue, 0.0); + if (hidValueRef == NULL) + { + break; + } + + CFRelease(hidValueRef); + hidInputClearCount++; + } while (1); + + if (hidInputClearCount > 0) + { + // HID input devices don't register events, so we need to manually prevent + // sleep and screensaver whenever we detect an input. + UpdateSystemActivity(UsrActivity); + } + + return hidInputClearCount; +} + +void HandleQueueValueAvailableCallback(void *inContext, IOReturn inResult, void *inSender) +{ + InputHIDManager *hidManager = (InputHIDManager *)inContext; + IOHIDQueueRef hidQueue = (IOHIDQueueRef)inSender; + id target = [hidManager target]; + + if (target != nil) + { + [[hidManager target] handleHIDQueue:hidQueue]; + } + else + { + // We must make sure the HID queue is emptied or else HID input will stall. + ClearHIDQueue(hidQueue); + } +} + +#pragma mark - +@implementation InputHIDManager + +@synthesize inputManager; +@synthesize hidManagerRef; +@synthesize deviceList; +@synthesize target; +@dynamic runLoop; + +- (id) initWithInputManager:(InputManager *)theInputManager +{ + self = [super init]; + if(self == nil) + { + return self; + } + + target = nil; + inputManager = [theInputManager retain]; + + hidManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hidManagerRef == NULL) + { + [self release]; + return nil; + } + + deviceList = [[NSMutableSet alloc] initWithCapacity:32]; + + CFMutableDictionaryRef cfJoystickMatcher = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(cfJoystickMatcher, CFSTR(kIOHIDDeviceUsagePageKey), (CFNumberRef)[NSNumber numberWithInteger:kHIDPage_GenericDesktop]); + CFDictionarySetValue(cfJoystickMatcher, CFSTR(kIOHIDDeviceUsageKey), (CFNumberRef)[NSNumber numberWithInteger:kHIDUsage_GD_Joystick]); + + CFMutableDictionaryRef cfGamepadMatcher = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(cfGamepadMatcher, CFSTR(kIOHIDDeviceUsagePageKey), (CFNumberRef)[NSNumber numberWithInteger:kHIDPage_GenericDesktop]); + CFDictionarySetValue(cfGamepadMatcher, CFSTR(kIOHIDDeviceUsageKey), (CFNumberRef)[NSNumber numberWithInteger:kHIDUsage_GD_GamePad]); + + NSArray *matcherArray = [[NSArray alloc] initWithObjects:(NSMutableDictionary *)cfJoystickMatcher, (NSMutableDictionary *)cfGamepadMatcher, nil]; + + IOHIDManagerSetDeviceMatchingMultiple(hidManagerRef, (CFArrayRef)matcherArray); + + [matcherArray release]; + CFRelease(cfJoystickMatcher); + CFRelease(cfGamepadMatcher); + + spinlockRunLoop = OS_SPINLOCK_INIT; + [self setRunLoop:[NSRunLoop currentRunLoop]]; + + IOReturn result = IOHIDManagerOpen(hidManagerRef, kIOHIDOptionsTypeNone); + if (result != kIOReturnSuccess) + { + [self release]; + return nil; + } + + return self; +} + +- (void)dealloc +{ + [self setRunLoop:nil]; + [self setInputManager:nil]; + [self setTarget:nil]; + + [deviceList release]; + + if (hidManagerRef != NULL) + { + IOHIDManagerClose(hidManagerRef, 0); + CFRelease(hidManagerRef); + hidManagerRef = NULL; + } + + [super dealloc]; +} + +- (void) setRunLoop:(NSRunLoop *)theRunLoop +{ + OSSpinLockLock(&spinlockRunLoop); + + if (theRunLoop == runLoop) + { + OSSpinLockUnlock(&spinlockRunLoop); + return; + } + + if (theRunLoop == nil) + { + IOHIDManagerRegisterDeviceMatchingCallback(hidManagerRef, NULL, NULL); + IOHIDManagerRegisterDeviceRemovalCallback(hidManagerRef, NULL, NULL); + IOHIDManagerUnscheduleFromRunLoop(hidManagerRef, [runLoop getCFRunLoop], kCFRunLoopDefaultMode); + } + else + { + [theRunLoop retain]; + IOHIDManagerScheduleWithRunLoop(hidManagerRef, [theRunLoop getCFRunLoop], kCFRunLoopDefaultMode); + IOHIDManagerRegisterDeviceMatchingCallback(hidManagerRef, HandleDeviceMatchingCallback, self); + IOHIDManagerRegisterDeviceRemovalCallback(hidManagerRef, HandleDeviceRemovalCallback, self); + } + + [runLoop release]; + runLoop = theRunLoop; + + OSSpinLockUnlock(&spinlockRunLoop); +} + +- (NSRunLoop *) runLoop +{ + OSSpinLockLock(&spinlockRunLoop); + NSRunLoop *theRunLoop = runLoop; + OSSpinLockUnlock(&spinlockRunLoop); + + return theRunLoop; +} + +@end + +void HandleDeviceMatchingCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) +{ + InputHIDManager *hidManager = (InputHIDManager *)inContext; + InputHIDDevice *newDevice = [[[InputHIDDevice alloc] initWithDevice:inIOHIDDeviceRef hidManager:hidManager] autorelease]; + [[hidManager deviceList] addObject:newDevice]; + [newDevice start]; +} + +void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) +{ + InputHIDManager *hidManager = (InputHIDManager *)inContext; + + for (InputHIDDevice *hidDevice in [hidManager deviceList]) + { + if ([hidDevice hidDeviceRef] == inIOHIDDeviceRef) + { + [[hidManager deviceList] removeObject:hidDevice]; + break; + } + } +} + +#pragma mark - +@implementation InputManager + +@synthesize emuControl; +@dynamic hidInputTarget; + +static std::tr1::unordered_map keyboardNameTable; // Key = Key code, Value = Key name + +- (id)init +{ + self = [super init]; + if (self == nil) + { + return self; + } + + if (keyboardNameTable.empty()) + { + NSDictionary *keyboardNameDict = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"KeyNames" ofType:@"plist"]]; + NSArray *keyboardDictKeyList = [keyboardNameDict allKeys]; + + for (NSString *dKey in keyboardDictKeyList) + { + unsigned short keyCode = (unsigned short)[dKey intValue]; + keyboardNameTable[keyCode] = std::string([(NSString *)[keyboardNameDict valueForKey:dKey] cStringUsingEncoding:NSUTF8StringEncoding]); + } + } + + hidManager = [[InputHIDManager alloc] initWithInputManager:self]; + + // Initialize the master command list. + CommandAttributes cmdDSControlRight = {@selector(cmdUpdateDSController:), DSControllerState_Right, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlLeft = {@selector(cmdUpdateDSController:), DSControllerState_Left, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlDown = {@selector(cmdUpdateDSController:), DSControllerState_Down, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlUp = {@selector(cmdUpdateDSController:), DSControllerState_Up, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlSelect = {@selector(cmdUpdateDSController:), DSControllerState_Select, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlStart = {@selector(cmdUpdateDSController:), DSControllerState_Start, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlB = {@selector(cmdUpdateDSController:), DSControllerState_B, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlA = {@selector(cmdUpdateDSController:), DSControllerState_A, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlY = {@selector(cmdUpdateDSController:), DSControllerState_Y, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlX = {@selector(cmdUpdateDSController:), DSControllerState_X, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlL = {@selector(cmdUpdateDSController:), DSControllerState_L, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlR = {@selector(cmdUpdateDSController:), DSControllerState_R, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlDebug = {@selector(cmdUpdateDSController:), DSControllerState_Debug, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlLid = {@selector(cmdUpdateDSController:), DSControllerState_Lid, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlTouch = {@selector(cmdUpdateDSController:), DSControllerState_Touch, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {YES, YES, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdDSControlMic = {@selector(cmdUpdateDSController:), DSControllerState_Microphone, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + + CommandAttributes cmdLoadEmuSaveStateSlot = {@selector(cmdLoadEmuSaveStateSlot:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {YES, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdSaveEmuSaveStateSlot = {@selector(cmdSaveEmuSaveStateSlot:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {YES, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdCopyScreen = {@selector(cmdCopyScreen:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdToggleSpeedHalf = {@selector(cmdToggleSpeedScalar:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.5f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdToggleSpeedDouble = {@selector(cmdToggleSpeedScalar:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {2.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdToggleSpeedLimiter = {@selector(cmdToggleSpeedLimiter:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdToggleAutoFrameSkip = {@selector(cmdToggleAutoFrameSkip:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdToggleCheats = {@selector(cmdToggleCheats:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdToggleExecutePause = {@selector(cmdToggleExecutePause:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdReset = {@selector(cmdReset:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {NO, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + CommandAttributes cmdToggleGPUState = {@selector(cmdToggleGPUState:), 0, INPUT_ATTRIBUTE_STATE_OFF, {0, 0, 0, 0}, {YES, NO, NO, NO}, {0.0f, 0.0f, 0.0f, 0.0f}, {NO, NO, NO, NO}, {NULL, NULL, NULL, NULL}, {NO, NO, NO, NO}}; + + commandMasterList["Up"] = cmdDSControlUp; + commandMasterList["Down"] = cmdDSControlDown; + commandMasterList["Right"] = cmdDSControlRight; + commandMasterList["Left"] = cmdDSControlLeft; + commandMasterList["A"] = cmdDSControlA; + commandMasterList["B"] = cmdDSControlB; + commandMasterList["X"] = cmdDSControlX; + commandMasterList["Y"] = cmdDSControlY; + commandMasterList["L"] = cmdDSControlL; + commandMasterList["R"] = cmdDSControlR; + commandMasterList["Start"] = cmdDSControlStart; + commandMasterList["Select"] = cmdDSControlSelect; + commandMasterList["Touch"] = cmdDSControlTouch; + commandMasterList["Microphone"] = cmdDSControlMic; + commandMasterList["Debug"] = cmdDSControlDebug; + commandMasterList["Lid"] = cmdDSControlLid; + + commandMasterList["Load State Slot"] = cmdLoadEmuSaveStateSlot; + commandMasterList["Save State Slot"] = cmdSaveEmuSaveStateSlot; + commandMasterList["Copy Screen"] = cmdCopyScreen; + commandMasterList["Speed Half"] = cmdToggleSpeedHalf; + commandMasterList["Speed Double"] = cmdToggleSpeedDouble; + commandMasterList["Enable/Disable Speed Limiter"] = cmdToggleSpeedLimiter; + commandMasterList["Enable/Disable Auto Frame Skip"] = cmdToggleAutoFrameSkip; + commandMasterList["Enable/Disable Cheats"] = cmdToggleCheats; + commandMasterList["Execute/Pause"] = cmdToggleExecutePause; + commandMasterList["Reset"] = cmdReset; + commandMasterList["Enable/Disable GPU State"] = cmdToggleGPUState; + + [self addMappingForIBAction:@selector(loadEmuSaveStateSlot:) commandTag:"Load State Slot"]; + [self addMappingForIBAction:@selector(saveEmuSaveStateSlot:) commandTag:"Save State Slot"]; + [self addMappingForIBAction:@selector(toggleSpeedHalf:) commandTag:"Speed Half"]; + [self addMappingForIBAction:@selector(toggleSpeedDouble:) commandTag:"Speed Double"]; + [self addMappingForIBAction:@selector(toggleSpeedLimiter:) commandTag:"Enable/Disable Speed Limiter"]; + [self addMappingForIBAction:@selector(toggleAutoFrameSkip:) commandTag:"Enable/Disable Auto Frame Skip"]; + [self addMappingForIBAction:@selector(toggleCheats:) commandTag:"Enable/Disable Cheats"]; + [self addMappingForIBAction:@selector(toggleExecutePause:) commandTag:"Execute/Pause"]; + [self addMappingForIBAction:@selector(reset:) commandTag:"Reset"]; + [self addMappingForIBAction:@selector(cmdToggleGPUState:) commandTag:"Enable/Disable GPU State"]; + + return self; +} + +- (void)dealloc +{ + [hidManager release]; + + [super dealloc]; +} + +#pragma mark Dynamic Properties + +- (void) setHidInputTarget:(id)theTarget +{ + [hidManager setTarget:theTarget]; +} + +- (id) hidInputTarget +{ + return [hidManager target]; +} + +#pragma mark Class Methods + +- (void) addMappingsUsingUserDefaults +{ + // Check to see if the DefaultKeyMappings.plist files exists. + NSDictionary *defaultMappings = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DefaultKeyMappings" ofType:@"plist"]]; + if (defaultMappings == nil) + { + return; + } + + NSDictionary *userMappings = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"Input_ControllerMappings"]; + if (userMappings == nil) + { + // If the input mappings does not exist in the user's preferences file, then copy all the mappings from the + // DefaultKeyMappings.plist file to the preferences file. + [[NSUserDefaults standardUserDefaults] setObject:defaultMappings forKey:@"Input_ControllerMappings"]; + } + else + { + // At this point, we need to check every key in the user's preference file and make sure that all the keys + // exist. The keys that must exist are all listed in the DefaultKeyMappings.plist file. + BOOL userMappingsDidChange = NO; + NSMutableDictionary *tempUserMappings = [NSMutableDictionary dictionaryWithDictionary:userMappings]; + + NSArray *inputKeys = [defaultMappings allKeys]; + for(NSString *inputString in inputKeys) + { + if ([tempUserMappings objectForKey:inputString] == nil) + { + [tempUserMappings setValue:[defaultMappings valueForKey:inputString] forKey:inputString]; + userMappingsDidChange = YES; + } + } + + // If we had to add a missing key, then we need to copy our temporary dictionary back to the + // user's preferences file. + if (userMappingsDidChange) + { + [[NSUserDefaults standardUserDefaults] setObject:tempUserMappings forKey:@"Input_ControllerMappings"]; + } + } + + NSArray *commandTagList = [defaultMappings allKeys]; + for(NSString *commandTag in commandTagList) + { + NSArray *deviceInfoList = (NSArray *)[userMappings valueForKey:commandTag]; + for(NSDictionary *deviceInfo in deviceInfoList) + { + [self addMappingUsingDeviceInfoDictionary:deviceInfo commandTag:[commandTag cStringUsingEncoding:NSUTF8StringEncoding]]; + } + } +} + +- (void) addMappingUsingDeviceInfoDictionary:(NSDictionary *)deviceInfo commandTag:(const char *)commandTag +{ + NSString *deviceCode = (NSString *)[deviceInfo valueForKey:@"deviceCode"]; + NSString *elementCode = (NSString *)[deviceInfo valueForKey:@"elementCode"]; + + if (deviceCode == nil || elementCode == nil || commandTag == NULL) + { + return; + } + + [self addMappingUsingDeviceCode:[deviceCode cStringUsingEncoding:NSUTF8StringEncoding] elementCode:[elementCode cStringUsingEncoding:NSUTF8StringEncoding] commandTag:commandTag]; +} + +- (void) addMappingUsingInputAttributes:(const InputAttributes *)inputAttr commandTag:(const char *)commandTag +{ + if (inputAttr == NULL || commandTag == NULL) + { + return; + } + + [self addMappingUsingDeviceCode:inputAttr->deviceCode.c_str() elementCode:inputAttr->elementCode.c_str() commandTag:commandTag]; +} + +- (void) addMappingUsingInputList:(const InputAttributesList *)inputList commandTag:(const char *)commandTag +{ + if (inputList == NULL || commandTag == NULL) + { + return; + } + + const size_t inputCount = inputList->size(); + + for (unsigned int i = 0; i < inputCount; i++) + { + const InputAttributes &inputAttr = (*inputList)[i]; + + if (inputAttr.inputState != INPUT_ATTRIBUTE_STATE_ON) + { + continue; + } + + [self addMappingUsingInputAttributes:&inputAttr commandTag:commandTag]; + } +} + +- (void) addMappingForIBAction:(const SEL)theSelector commandTag:(const char *)commandTag +{ + if (theSelector == nil || commandTag == NULL) + { + return; + } + + [self addMappingUsingDeviceCode:"IBAction" elementCode:sel_getName(theSelector) commandTag:commandTag]; +} + +- (void) addMappingUsingDeviceCode:(const char *)deviceCode elementCode:(const char *)elementCode commandTag:(const char *)commandTag +{ + if (deviceCode == NULL || elementCode == NULL || commandTag == NULL) + { + return; + } + + // Remove all mappings to commandTag in order to force a 1:1 mapping (except for IBAction mappings). + // TODO: Remove this restriction when the code supports multiple inputs being mapped to the same command tag. + [self removeAllMappingsOfCommandTag:commandTag]; + + const std::string inputKey = std::string(deviceCode) + ":" + std::string(elementCode); + commandMap[inputKey] = std::string(commandTag); +} + +- (void) removeMappingUsingDeviceCode:(const char *)deviceCode elementCode:(const char *)elementCode +{ + if (deviceCode == NULL || elementCode == NULL) + { + return; + } + + const std::string inputKey = std::string(deviceCode) + ":" + std::string(elementCode); + + CommandTagMap::iterator it = commandMap.find(inputKey); + if (it != commandMap.end()) + { + commandMap.erase(it); + } +} + +- (void) removeAllMappingsOfCommandTag:(const char *)commandTag +{ + if (commandTag == NULL) + { + return; + } + + // This loop removes all mappings to commandTag, with the exception of IBAction mappings. + for (CommandTagMap::iterator it=commandMap.begin(); it!=commandMap.end(); ++it) + { + if (it->first.find("IBAction") == std::string::npos && it->second == std::string(commandTag)) + { + commandMap.erase(it); + } + } +} + +- (CommandAttributesList) generateCommandListUsingInputList:(const InputAttributesList *)inputList +{ + CommandAttributesList cmdList; + size_t inputCount = inputList->size(); + + for (unsigned int i = 0; i < inputCount; i++) + { + const InputAttributes &inputAttr = (*inputList)[i]; + + // All inputs require a device code and element code for mapping. If one or both are + // not present, reject the input. + if (inputAttr.deviceCode.empty() || inputAttr.elementCode.empty()) + { + continue; + } + + // Look up the command key using the input key. + const std::string inputKey = inputAttr.deviceCode + ":" + inputAttr.elementCode; + const std::string commandTag = commandMap[inputKey]; + + if (commandTag.empty()) + { + continue; + } + + // Look up the command attributes using the command key. + CommandAttributes cmdAttr = commandMasterList[commandTag]; + cmdAttr.inputState = inputAttr.inputState; + + // Override command values with input values as necessary. + for (unsigned int j = 0; j < INPUT_HANDLER_MAX_ATTRIBUTE_VALUES; j++) + { + if (cmdAttr.useIntegerInputValue[j]) + { + cmdAttr.integerValue[j] = inputAttr.integerValue[j]; + } + + if (cmdAttr.useFloatInputValue[j]) + { + cmdAttr.floatValue[j] = inputAttr.floatValue[j]; + } + + if (cmdAttr.useObjectInputValue[j]) + { + cmdAttr.object[j] = inputAttr.object[j]; + } + } + + cmdList.push_back(cmdAttr); + } + + return cmdList; +} + +- (void) dispatchCommandList:(const CommandAttributesList *)cmdList +{ + size_t cmdCount = cmdList->size(); + for (size_t i = 0; i < cmdCount; i++) + { + const CommandAttributes &cmdAttr = (*cmdList)[i]; + + if ([emuControl respondsToSelector:cmdAttr.selector]) + { + [emuControl performSelector:cmdAttr.selector withObject:[NSValue valueWithBytes:&cmdAttr objCType:@encode(CommandAttributes)]]; + } + } +} + +- (BOOL) dispatchCommandUsingInputAttributes:(const InputAttributes *)inputAttr +{ + BOOL didCommandDispatch = NO; + + // All inputs require a device code and element code for mapping. If one or both are + // not present, reject the input. + if (inputAttr->deviceCode.empty() || inputAttr->elementCode.empty()) + { + return didCommandDispatch; + } + + // Look up the command key using the input key. + const std::string inputKey = inputAttr->deviceCode + ":" + inputAttr->elementCode; + const std::string commandTag = commandMap[inputKey]; + + if (commandTag.empty()) + { + return didCommandDispatch; + } + + // Look up the command attributes using the command key. + CommandAttributes cmdAttr = commandMasterList[commandTag]; + cmdAttr.inputState = inputAttr->inputState; + + // Override command values with input values as necessary. + for (unsigned int j = 0; j < INPUT_HANDLER_MAX_ATTRIBUTE_VALUES; j++) + { + if (cmdAttr.useIntegerInputValue[j]) + { + cmdAttr.integerValue[j] = inputAttr->integerValue[j]; + } + + if (cmdAttr.useFloatInputValue[j]) + { + cmdAttr.floatValue[j] = inputAttr->floatValue[j]; + } + + if (cmdAttr.useObjectInputValue[j]) + { + cmdAttr.object[j] = inputAttr->object[j]; + } + } + + if ([emuControl respondsToSelector:cmdAttr.selector]) + { + [emuControl performSelector:cmdAttr.selector withObject:[NSValue valueWithBytes:&cmdAttr objCType:@encode(CommandAttributes)]]; + } + + didCommandDispatch = YES; + return didCommandDispatch; +} + +- (BOOL) dispatchCommandUsingIBAction:(const SEL)theSelector tag:(NSInteger)tagValue +{ + InputAttributes inputAttr = InputManagerEncodeIBAction(theSelector, tagValue); + return [self dispatchCommandUsingInputAttributes:&inputAttr]; +} + +- (void) writeUserDefaultsMappingUsingInputAttributes:(const InputAttributes *)inputAttr commandTag:(const char *)commandTag +{ + NSString *deviceCode = [NSString stringWithCString:inputAttr->deviceCode.c_str() encoding:NSUTF8StringEncoding]; + NSString *deviceName = [NSString stringWithCString:inputAttr->deviceName.c_str() encoding:NSUTF8StringEncoding]; + NSString *elementCode = [NSString stringWithCString:inputAttr->elementCode.c_str() encoding:NSUTF8StringEncoding]; + NSString *elementName = [NSString stringWithCString:inputAttr->elementName.c_str() encoding:NSUTF8StringEncoding]; + NSString *commandTagString = [NSString stringWithCString:commandTag encoding:NSUTF8StringEncoding]; + + NSDictionary *deviceInfo = [NSDictionary dictionaryWithObjectsAndKeys: + deviceCode, @"deviceCode", + deviceName, @"deviceName", + elementCode, @"elementCode", + elementName, @"elementName", + nil]; + + NSMutableDictionary *tempUserMappings = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"Input_ControllerMappings"]]; + [tempUserMappings setValue:[NSArray arrayWithObject:deviceInfo] forKey:commandTagString]; + [[NSUserDefaults standardUserDefaults] setValue:tempUserMappings forKey:@"Input_ControllerMappings"]; +} + +InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue) +{ + InputAttributesList inputList; + if (hidQueue == nil) + { + return inputList; + } + + do + { + IOHIDValueRef hidValueRef = IOHIDQueueCopyNextValueWithTimeout(hidQueue, 0.0); + if (hidValueRef == NULL) + { + break; + } + + InputAttributesList hidInputList = InputListFromHatSwitchValue(hidValueRef, false); + if (hidInputList.empty()) + { + hidInputList = InputListFromHIDValue(hidValueRef); + } + + size_t hidInputCount = hidInputList.size(); + for (unsigned int i = 0; i < hidInputCount; i++) + { + if (hidInputList[i].deviceCode.empty() || hidInputList[i].elementCode.empty()) + { + continue; + } + + inputList.push_back(hidInputList[i]); + } + + CFRelease(hidValueRef); + } while (1); + + if (!inputList.empty()) + { + // HID input devices don't register events, so we need to manually prevent + // sleep and screensaver whenever we detect an input. + UpdateSystemActivity(UsrActivity); + } + + return inputList; +} + +InputAttributes InputManagerEncodeKeyboardInput(const unsigned short keyCode, BOOL keyPressed) +{ + std::string elementName = keyboardNameTable[keyCode]; + char elementCodeBuf[256] = {0}; + snprintf(elementCodeBuf, 256, "%d", keyCode); + + InputAttributes inputAttr; + inputAttr.deviceCode = "NSEventKeyboard"; + inputAttr.deviceName = "Keyboard"; + inputAttr.elementCode = std::string(elementCodeBuf); + inputAttr.elementName = (elementName.empty()) ? inputAttr.elementCode : elementName; + inputAttr.inputState = (keyPressed) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF; + + return inputAttr; +} + +InputAttributes InputManagerEncodeMouseButtonInput(const NSInteger buttonNumber, const NSPoint touchLoc, BOOL buttonPressed) +{ + char elementNameBuf[256] = {0}; + snprintf(elementNameBuf, 256, "Button %i", (int)buttonNumber); + + char elementCodeBuf[256] = {0}; + snprintf(elementCodeBuf, 256, "%i", (int)buttonNumber); + + switch (buttonNumber) + { + case kCGMouseButtonLeft: + strncpy(elementNameBuf, "Primary Button", 256); + break; + + case kCGMouseButtonRight: + strncpy(elementNameBuf, "Secondary Button", 256); + break; + + case kCGMouseButtonCenter: + strncpy(elementNameBuf, "Center Button", 256); + break; + + default: + break; + } + + InputAttributes inputAttr; + inputAttr.deviceCode = "NSEventMouse"; + inputAttr.deviceName = "Mouse"; + inputAttr.elementCode = std::string(elementCodeBuf); + inputAttr.elementName = std::string(elementNameBuf); + inputAttr.inputState = (buttonPressed) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF; + inputAttr.floatValue[0] = touchLoc.x; + inputAttr.floatValue[1] = touchLoc.y; + + return inputAttr; +} + +InputAttributes InputManagerEncodeIBAction(const SEL theSelector, const NSInteger tagValue) +{ + InputAttributes inputAttr; + inputAttr.deviceCode = "IBAction"; + inputAttr.deviceName = "Application"; + inputAttr.elementCode = std::string(sel_getName(theSelector)); + inputAttr.elementName = inputAttr.elementCode; + inputAttr.integerValue[0] = tagValue; + + return inputAttr; +} + +@end diff --git a/desmume/src/cocoa/userinterface/appDelegate.h b/desmume/src/cocoa/userinterface/appDelegate.h index 5c5e756f7..069bfaa6f 100644 --- a/desmume/src/cocoa/userinterface/appDelegate.h +++ b/desmume/src/cocoa/userinterface/appDelegate.h @@ -19,8 +19,7 @@ #import @class InputPrefsView; -@class CocoaHIDManager; -@class EmuControllerDelegate; +@class InputManager; #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 @@ -39,6 +38,7 @@ NSObjectController *prefWindowController; NSObjectController *cheatWindowController; NSObjectController *cdsCoreController; + InputManager *inputManager; NSWindow *prefWindow; NSWindow *troubleshootingWindow; @@ -56,7 +56,6 @@ NSBox *boxFileSystem; NSBox *boxMisc; - CocoaHIDManager *hidManager; BOOL migrationFilesPresent; BOOL isAppRunningOnIntel; } @@ -71,6 +70,7 @@ @property (readonly) IBOutlet NSObjectController *prefWindowController; @property (readonly) IBOutlet NSObjectController *cheatWindowController; @property (readonly) IBOutlet NSObjectController *cdsCoreController; +@property (readonly) IBOutlet InputManager *inputManager; @property (readonly) IBOutlet NSWindow *prefWindow; @property (readonly) IBOutlet NSWindow *troubleshootingWindow; @property (readonly) IBOutlet NSWindow *cheatListWindow; @@ -86,7 +86,6 @@ @property (readonly) IBOutlet NSBox *boxFileSystem; @property (readonly) IBOutlet NSBox *boxMisc; -@property (retain) CocoaHIDManager *hidManager; @property (assign) BOOL migrationFilesPresent; @property (assign) BOOL isAppRunningOnIntel; diff --git a/desmume/src/cocoa/userinterface/appDelegate.mm b/desmume/src/cocoa/userinterface/appDelegate.mm index 0a183a48d..ad9d0e630 100644 --- a/desmume/src/cocoa/userinterface/appDelegate.mm +++ b/desmume/src/cocoa/userinterface/appDelegate.mm @@ -28,7 +28,6 @@ #import "cocoa_file.h" #import "cocoa_firmware.h" #import "cocoa_globals.h" -#import "cocoa_hid.h" #import "cocoa_input.h" #import "cocoa_mic.h" #import "cocoa_rom.h" @@ -54,6 +53,7 @@ @synthesize prefWindowController; @synthesize cdsCoreController; @synthesize cheatWindowController; +@synthesize inputManager; @synthesize boxGeneralInfo; @synthesize boxTitles; @@ -61,7 +61,6 @@ @synthesize boxFileSystem; @synthesize boxMisc; -@synthesize hidManager; @synthesize migrationFilesPresent; @synthesize isAppRunningOnIntel; @@ -168,9 +167,6 @@ // Builder because we're assuming an arbitrary number of slot items. [self setupSlotMenuItems]; - // Setup the HID Input manager. - [self setHidManager:[[[CocoaHIDManager alloc] init] autorelease]]; - // Init the DS emulation core. CocoaDSCore *newCore = [[[CocoaDSCore alloc] init] autorelease]; [cdsCoreController setContent:newCore]; @@ -179,7 +175,6 @@ CocoaDSMic *newMic = [[[CocoaDSMic alloc] init] autorelease]; CocoaDSController *newController = [[[CocoaDSController alloc] initWithMic:newMic] autorelease]; [newCore setCdsController:newController]; - [inputPrefsView setCdsController:newController]; // Init the DS speakers. CocoaDSSpeaker *newSpeaker = [[[CocoaDSSpeaker alloc] init] autorelease]; @@ -511,6 +506,7 @@ [prefWindowDelegate updateVolumeIcon:nil]; [emuControl setupUserDefaults]; + [inputManager addMappingsUsingUserDefaults]; } - (void) updateInputDisplayFields @@ -523,27 +519,27 @@ return; } - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Up"] forKey:@"Input_Up"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Down"] forKey:@"Input_Down"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Left"] forKey:@"Input_Left"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Right"] forKey:@"Input_Right"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"A"] forKey:@"Input_A"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"B"] forKey:@"Input_B"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"X"] forKey:@"Input_X"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Y"] forKey:@"Input_Y"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"L"] forKey:@"Input_L"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"R"] forKey:@"Input_R"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Start"] forKey:@"Input_Start"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Select"] forKey:@"Input_Select"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Microphone"] forKey:@"Input_Microphone"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Lid"] forKey:@"Input_Lid"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Debug"] forKey:@"Input_Debug"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Speed Half"] forKey:@"Input_SpeedHalf"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Speed Double"] forKey:@"Input_SpeedDouble"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"HUD"] forKey:@"Input_HUD"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Execute"] forKey:@"Input_Execute"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Pause"] forKey:@"Input_Pause"]; - [prefBindings setValue:[inputPrefsView parseMappingDisplayString:@"Reset"] forKey:@"Input_Reset"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Up"] forKey:@"Input_Up"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Down"] forKey:@"Input_Down"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Left"] forKey:@"Input_Left"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Right"] forKey:@"Input_Right"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"A"] forKey:@"Input_A"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"B"] forKey:@"Input_B"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"X"] forKey:@"Input_X"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Y"] forKey:@"Input_Y"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"L"] forKey:@"Input_L"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"R"] forKey:@"Input_R"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Start"] forKey:@"Input_Start"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Select"] forKey:@"Input_Select"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Microphone"] forKey:@"Input_Microphone"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Lid"] forKey:@"Input_Lid"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Debug"] forKey:@"Input_Debug"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Speed Half"] forKey:@"Input_SpeedHalf"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Speed Double"] forKey:@"Input_SpeedDouble"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"HUD"] forKey:@"Input_HUD"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Execute"] forKey:@"Input_Execute"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Pause"] forKey:@"Input_Pause"]; + [prefBindings setValue:[inputPrefsView parseMappingDisplayString:"Reset"] forKey:@"Input_Reset"]; } - (IBAction) showMigrationWindow:(id)sender diff --git a/desmume/src/cocoa/userinterface/inputPrefsView.h b/desmume/src/cocoa/userinterface/inputPrefsView.h index da23ec633..28903c906 100644 --- a/desmume/src/cocoa/userinterface/inputPrefsView.h +++ b/desmume/src/cocoa/userinterface/inputPrefsView.h @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2012 DeSmuME team + Copyright (C) 2012-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,32 +17,31 @@ */ #import +#import "InputManager.h" @class CocoaDSController; -@interface InputPrefsView : NSView +@interface InputPrefsView : NSView { NSWindow *prefWindow; + InputManager *inputManager; NSButton *lastConfigButton; - NSInteger configInput; + NSInteger configInputTargetID; NSMutableDictionary *configInputList; - NSDictionary *keyNameTable; - CocoaDSController *cdsController; + std::tr1::unordered_map commandTagMap; // Key = Command ID, Value = Command Tag + NSDictionary *displayStringBindings; } @property (readonly) IBOutlet NSWindow *prefWindow; -@property (assign) NSInteger configInput; -@property (retain) CocoaDSController *cdsController; +@property (readonly) IBOutlet InputManager *inputManager; +@property (assign) NSInteger configInputTargetID; + +- (BOOL) handleKeyboardEvent:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed; +- (BOOL) handleMouseButtonEvent:(NSEvent *)mouseEvent buttonPressed:(BOOL)buttonPressed; +- (NSString *) parseMappingDisplayString:(const char *)commandTag; -- (BOOL) handleMouseDown:(NSEvent *)mouseEvent; -- (void) addMappingById:(NSInteger)dsControlID deviceCode:(NSString *)deviceCode deviceName:(NSString *)deviceName elementCode:(NSString *)elementCode elementName:(NSString *)elementName; -- (void) addMappingByKey:(NSString *)dsControlKey deviceCode:(NSString *)deviceCode deviceName:(NSString *)deviceName elementCode:(NSString *)elementCode elementName:(NSString *)elementName; -- (void) addMappingByKey:(NSString *)dsControlKey deviceInfo:(NSDictionary *)deviceInfo; -- (NSString *) parseMappingDisplayString:(NSString *)keyString; - (IBAction) inputButtonSet:(id)sender; -- (void) inputButtonCancelConfig; -- (void) handleHIDInput:(NSNotification *)aNotification; @end diff --git a/desmume/src/cocoa/userinterface/inputPrefsView.mm b/desmume/src/cocoa/userinterface/inputPrefsView.mm index 008b00060..273b4cee9 100644 --- a/desmume/src/cocoa/userinterface/inputPrefsView.mm +++ b/desmume/src/cocoa/userinterface/inputPrefsView.mm @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2012 DeSmuME team + Copyright (C) 2012-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,8 +27,8 @@ @implementation InputPrefsView @synthesize prefWindow; -@synthesize configInput; -@synthesize cdsController; +@synthesize inputManager; +@dynamic configInputTargetID; - (id)initWithFrame:(NSRect)frame { @@ -39,44 +39,239 @@ } lastConfigButton = nil; - configInput = 0; + configInputTargetID = 0; configInputList = [[NSMutableDictionary alloc] initWithCapacity:32]; - keyNameTable = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"KeyNames" ofType:@"plist"]]; - cdsController = nil; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleHIDInput:) - name:@"org.desmume.DeSmuME.hidInputDetected" - object:nil]; + displayStringBindings = [[NSDictionary alloc] initWithObjectsAndKeys: + @"Input_Up", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_UP], + @"Input_Down", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_DOWN], + @"Input_Left", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_LEFT], + @"Input_Right", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_RIGHT], + @"Input_A", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_A], + @"Input_B", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_B], + @"Input_X", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_X], + @"Input_Y", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_Y], + @"Input_L", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_L], + @"Input_R", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_R], + @"Input_Start", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_START], + @"Input_Select", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_SELECT], + @"Input_Microphone", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_SIM_MIC], + @"Input_Lid", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_LID], + @"Input_Debug", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_DEBUG], + @"Input_SpeedHalf", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_SPEED_HALF], + @"Input_SpeedDouble", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_SPEED_DOUBLE], + @"Input_HUD", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_TOGGLE_HUD], + @"Input_Execute", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_EXECUTE], + @"Input_Pause", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_PAUSE], + @"Input_Reset", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_RESET], + @"Input_Touch", [NSString stringWithFormat:@"%i", PREF_INPUT_BUTTON_TOUCH], + nil]; + + commandTagMap[PREF_INPUT_BUTTON_UP] = "Up"; + commandTagMap[PREF_INPUT_BUTTON_DOWN] = "Down"; + commandTagMap[PREF_INPUT_BUTTON_LEFT] = "Left"; + commandTagMap[PREF_INPUT_BUTTON_RIGHT] = "Right"; + commandTagMap[PREF_INPUT_BUTTON_A] = "A"; + commandTagMap[PREF_INPUT_BUTTON_B] = "B"; + commandTagMap[PREF_INPUT_BUTTON_X] = "X"; + commandTagMap[PREF_INPUT_BUTTON_Y] = "Y"; + commandTagMap[PREF_INPUT_BUTTON_L] = "L"; + commandTagMap[PREF_INPUT_BUTTON_R] = "R"; + commandTagMap[PREF_INPUT_BUTTON_START] = "Start"; + commandTagMap[PREF_INPUT_BUTTON_SELECT] = "Select"; + commandTagMap[PREF_INPUT_BUTTON_SIM_MIC] = "Microphone"; + commandTagMap[PREF_INPUT_BUTTON_LID] = "Lid"; + commandTagMap[PREF_INPUT_BUTTON_DEBUG] = "Debug"; + commandTagMap[PREF_INPUT_BUTTON_SPEED_HALF] = "Speed Half"; + commandTagMap[PREF_INPUT_BUTTON_SPEED_DOUBLE] = "Speed Double"; + commandTagMap[PREF_INPUT_BUTTON_TOGGLE_HUD] = "HUD"; + commandTagMap[PREF_INPUT_BUTTON_EXECUTE] = "Execute"; + commandTagMap[PREF_INPUT_BUTTON_PAUSE] = "Pause"; + commandTagMap[PREF_INPUT_BUTTON_RESET] = "Reset"; + commandTagMap[PREF_INPUT_BUTTON_TOUCH] = "Touch"; return self; } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [configInputList release]; - [keyNameTable release]; + [displayStringBindings release]; [super dealloc]; } +#pragma mark Dynamic Properties +- (void) setConfigInputTargetID:(NSInteger)targetID +{ + if (targetID == 0) + { + [lastConfigButton setState:NSOffState]; + lastConfigButton = nil; + } + + configInputTargetID = targetID; + [[self inputManager] setHidInputTarget:(targetID == 0) ? nil : self]; +} + +- (NSInteger) configInputTargetID +{ + return configInputTargetID; +} + +#pragma mark Class Methods + +- (BOOL) handleKeyboardEvent:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed +{ + BOOL isHandled = NO; + + if ([self configInputTargetID] == 0) + { + return isHandled; + } + + std::string commandTag = commandTagMap[[self configInputTargetID]]; + if (commandTag.empty()) + { + return isHandled; + } + + InputAttributes inputAttr = InputManagerEncodeKeyboardInput([theEvent keyCode], keyPressed); + [inputManager addMappingUsingInputAttributes:&inputAttr commandTag:commandTag.c_str()]; + [inputManager writeUserDefaultsMappingUsingInputAttributes:&inputAttr commandTag:commandTag.c_str()]; + + NSMutableDictionary *prefWindowBindings = [(PreferencesWindowDelegate *)[prefWindow delegate] bindings]; + NSString *displayBinding = (NSString *)[displayStringBindings valueForKey:[NSString stringWithFormat:@"%i", [self configInputTargetID]]]; + [prefWindowBindings setValue:[self parseMappingDisplayString:commandTag.c_str()] forKey:displayBinding]; + + [self setConfigInputTargetID:0]; + + isHandled = YES; + return isHandled; +} + +- (BOOL) handleMouseButtonEvent:(NSEvent *)mouseEvent buttonPressed:(BOOL)buttonPressed +{ + BOOL isHandled = NO; + + if ([self configInputTargetID] == 0) + { + return isHandled; + } + + std::string commandTag = commandTagMap[[self configInputTargetID]]; + if (commandTag.empty()) + { + return isHandled; + } + + InputAttributes inputAttr = InputManagerEncodeMouseButtonInput([mouseEvent buttonNumber], NSMakePoint(0.0f, 0.0f), buttonPressed); + [inputManager addMappingUsingInputAttributes:&inputAttr commandTag:commandTag.c_str()]; + [inputManager writeUserDefaultsMappingUsingInputAttributes:&inputAttr commandTag:commandTag.c_str()]; + + NSMutableDictionary *prefWindowBindings = [(PreferencesWindowDelegate *)[prefWindow delegate] bindings]; + NSString *displayBinding = (NSString *)[displayStringBindings valueForKey:[NSString stringWithFormat:@"%i", [self configInputTargetID]]]; + [prefWindowBindings setValue:[self parseMappingDisplayString:commandTag.c_str()] forKey:displayBinding]; + + [self setConfigInputTargetID:0]; + + isHandled = YES; + return isHandled; +} + +- (NSString *) parseMappingDisplayString:(const char *)commandTag +{ + NSDictionary *userMappings = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"Input_ControllerMappings"]; + NSArray *mappingList = (NSArray *)[userMappings valueForKey:[NSString stringWithCString:commandTag encoding:NSUTF8StringEncoding]]; + NSDictionary *mapping = (NSDictionary *)[mappingList objectAtIndex:0]; + NSString *deviceName = (NSString *)[mapping valueForKey:@"deviceName"]; + NSString *elementName = (NSString *)[mapping valueForKey:@"elementName"]; + + NSString *displayString = [NSString stringWithString:deviceName]; + displayString = [displayString stringByAppendingString:@": "]; + displayString = [displayString stringByAppendingString:elementName]; + + return displayString; +} + +#pragma mark InputHIDManagerTarget Protocol +- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue +{ + BOOL isHandled = NO; + + if ([self configInputTargetID] == 0) + { + ClearHIDQueue(hidQueue); + return isHandled; + } + + InputAttributesList inputList = InputManagerEncodeHIDQueue(hidQueue); + const size_t inputCount = inputList.size(); + + for (unsigned int i = 0; i < inputCount; i++) + { + const InputAttributes &inputAttr = inputList[i]; + const std::string inputKey = inputAttr.deviceCode + ":" + inputAttr.elementCode; + NSString *inputKeyStr = [NSString stringWithCString:inputKey.c_str() encoding:NSUTF8StringEncoding]; + NSDate *inputOnDate = [configInputList valueForKey:inputKeyStr]; + + if (inputAttr.inputState == INPUT_ATTRIBUTE_STATE_ON) + { + if (inputOnDate == nil) + { + [configInputList setValue:[NSDate date] forKey:inputKeyStr]; + } + } + else + { + if (inputOnDate != nil) + { + if (([inputOnDate timeIntervalSinceNow] * -1.0) < INPUT_HOLD_TIME) + { + // If the button isn't held for at least INPUT_HOLD_TIME seconds, then reject the input. + [configInputList setValue:nil forKey:inputKeyStr]; + } + else + { + std::string commandTag = commandTagMap[[self configInputTargetID]]; + if (commandTag.empty()) + { + continue; + } + + // Add the input mapping. + [inputManager addMappingUsingInputAttributes:&inputAttr commandTag:commandTag.c_str()]; + [inputManager writeUserDefaultsMappingUsingInputAttributes:&inputAttr commandTag:commandTag.c_str()]; + + NSMutableDictionary *prefWindowBindings = [(PreferencesWindowDelegate *)[prefWindow delegate] bindings]; + NSString *displayBinding = (NSString *)[displayStringBindings valueForKey:[NSString stringWithFormat:@"%i", [self configInputTargetID]]]; + [prefWindowBindings setValue:[self parseMappingDisplayString:commandTag.c_str()] forKey:displayBinding]; + + [self setConfigInputTargetID:0]; + break; + } + } + } + } + + isHandled = YES; + return isHandled; +} + +#pragma mark NSResponder Methods + - (void)keyDown:(NSEvent *)theEvent { - NSString *elementCode = [NSString stringWithFormat:@"%d", [theEvent keyCode]]; - NSString *elementName = (NSString *)[keyNameTable valueForKey:elementCode]; - - if (configInput != 0) + BOOL isHandled = [self handleKeyboardEvent:theEvent keyPressed:YES]; + if (!isHandled) { - [self addMappingById:configInput deviceCode:@"NSEventKeyboard" deviceName:@"Keyboard" elementCode:elementCode elementName:elementName]; - [self inputButtonCancelConfig]; + [super keyDown:theEvent]; } } - (void)mouseDown:(NSEvent *)theEvent { - BOOL isHandled = [self handleMouseDown:theEvent]; + BOOL isHandled = [self handleMouseButtonEvent:theEvent buttonPressed:YES]; if (!isHandled) { [super mouseDown:theEvent]; @@ -90,7 +285,7 @@ - (void)rightMouseDown:(NSEvent *)theEvent { - BOOL isHandled = [self handleMouseDown:theEvent]; + BOOL isHandled = [self handleMouseButtonEvent:theEvent buttonPressed:YES]; if (!isHandled) { [super rightMouseDown:theEvent]; @@ -104,7 +299,7 @@ - (void)otherMouseDown:(NSEvent *)theEvent { - BOOL isHandled = [self handleMouseDown:theEvent]; + BOOL isHandled = [self handleMouseButtonEvent:theEvent buttonPressed:YES]; if (!isHandled) { [super otherMouseDown:theEvent]; @@ -116,263 +311,6 @@ [self otherMouseDown:theEvent]; } -- (BOOL) handleMouseDown:(NSEvent *)mouseEvent -{ - BOOL isHandled = NO; - NSString *elementCode = [NSString stringWithFormat:@"%li", (long)[mouseEvent buttonNumber]]; - NSString *elementName = [NSString stringWithFormat:@"Button %li", (long)[mouseEvent buttonNumber]]; - - switch ([mouseEvent buttonNumber]) - { - case kCGMouseButtonLeft: - elementName = @"Primary Button"; - break; - - case kCGMouseButtonRight: - elementName = @"Secondary Button"; - break; - - case kCGMouseButtonCenter: - elementName = @"Center Button"; - break; - - default: - break; - } - - if (configInput != 0) - { - [self addMappingById:configInput deviceCode:@"NSEventMouse" deviceName:@"Mouse" elementCode:elementCode elementName:elementName]; - [self inputButtonCancelConfig]; - isHandled = YES; - } - - return isHandled; -} - -- (void) addMappingById:(NSInteger)dsControlID deviceCode:(NSString *)deviceCode deviceName:(NSString *)deviceName elementCode:(NSString *)elementCode elementName:(NSString *)elementName -{ - NSString *dsControlKey = nil; - NSString *displayBindingsKey = nil; - - switch (dsControlID) - { - case PREF_INPUT_BUTTON_UP: - dsControlKey = @"Up"; - displayBindingsKey = @"Input_Up"; - break; - - case PREF_INPUT_BUTTON_DOWN: - dsControlKey = @"Down"; - displayBindingsKey = @"Input_Down"; - break; - - case PREF_INPUT_BUTTON_LEFT: - dsControlKey = @"Left"; - displayBindingsKey = @"Input_Left"; - break; - - case PREF_INPUT_BUTTON_RIGHT: - dsControlKey = @"Right"; - displayBindingsKey = @"Input_Right"; - break; - - case PREF_INPUT_BUTTON_A: - dsControlKey = @"A"; - displayBindingsKey = @"Input_A"; - break; - - case PREF_INPUT_BUTTON_B: - dsControlKey = @"B"; - displayBindingsKey = @"Input_B"; - break; - - case PREF_INPUT_BUTTON_X: - dsControlKey = @"X"; - displayBindingsKey = @"Input_X"; - break; - - case PREF_INPUT_BUTTON_Y: - dsControlKey = @"Y"; - displayBindingsKey = @"Input_Y"; - break; - - case PREF_INPUT_BUTTON_L: - dsControlKey = @"L"; - displayBindingsKey = @"Input_L"; - break; - - case PREF_INPUT_BUTTON_R: - dsControlKey = @"R"; - displayBindingsKey = @"Input_R"; - break; - - case PREF_INPUT_BUTTON_START: - dsControlKey = @"Start"; - displayBindingsKey = @"Input_Start"; - break; - - case PREF_INPUT_BUTTON_SELECT: - dsControlKey = @"Select"; - displayBindingsKey = @"Input_Select"; - break; - - case PREF_INPUT_BUTTON_SIM_MIC: - dsControlKey = @"Microphone"; - displayBindingsKey = @"Input_Microphone"; - break; - - case PREF_INPUT_BUTTON_LID: - dsControlKey = @"Lid"; - displayBindingsKey = @"Input_Lid"; - break; - - case PREF_INPUT_BUTTON_DEBUG: - dsControlKey = @"Debug"; - displayBindingsKey = @"Input_Debug"; - break; - - case PREF_INPUT_BUTTON_SPEED_HALF: - dsControlKey = @"Speed Half"; - displayBindingsKey = @"Input_SpeedHalf"; - break; - - case PREF_INPUT_BUTTON_SPEED_DOUBLE: - dsControlKey = @"Speed Double"; - displayBindingsKey = @"Input_SpeedDouble"; - break; - - case PREF_INPUT_BUTTON_TOGGLE_HUD: - dsControlKey = @"HUD"; - displayBindingsKey = @"Input_HUD"; - break; - - case PREF_INPUT_BUTTON_EXECUTE: - dsControlKey = @"Execute"; - displayBindingsKey = @"Input_Execute"; - break; - - case PREF_INPUT_BUTTON_PAUSE: - dsControlKey = @"Pause"; - displayBindingsKey = @"Input_Pause"; - break; - - case PREF_INPUT_BUTTON_RESET: - dsControlKey = @"Reset"; - displayBindingsKey = @"Input_Reset"; - break; - - case PREF_INPUT_BUTTON_TOUCH: - dsControlKey = @"Touch"; - break; - - default: - return; - break; - } - - if (dsControlKey != nil) - { - [self addMappingByKey:dsControlKey deviceCode:deviceCode deviceName:deviceName elementCode:elementCode elementName:elementName]; - if (dsControlID != PREF_INPUT_BUTTON_TOUCH) - { - NSMutableDictionary *prefWindowBindings = [(PreferencesWindowDelegate *)[prefWindow delegate] bindings]; - [prefWindowBindings setValue:[self parseMappingDisplayString:dsControlKey] forKey:displayBindingsKey]; - } - } -} - -- (void) addMappingByKey:(NSString *)dsControlKey deviceCode:(NSString *)deviceCode deviceName:(NSString *)deviceName elementCode:(NSString *)elementCode elementName:(NSString *)elementName -{ - if (deviceCode == nil || elementCode == nil) - { - return; - } - - if (deviceName == nil) - { - deviceName = deviceCode; - } - - if (elementName == nil) - { - elementName = elementCode; - } - - BOOL useDeviceValues = NO; - if ([deviceCode isEqualToString:@"NSEventMouse"]) - { - useDeviceValues = YES; - } - - NSDictionary *deviceInfo = [NSDictionary dictionaryWithObjectsAndKeys: - deviceCode, @"deviceCode", - deviceName, @"deviceName", - elementCode, @"elementCode", - elementName, @"elementName", - [NSNumber numberWithBool:useDeviceValues], @"useDeviceValues", - nil]; - - [self addMappingByKey:dsControlKey deviceInfo:deviceInfo]; -} - -- (void) addMappingByKey:(NSString *)dsControlKey deviceInfo:(NSDictionary *)deviceInfo -{ - [cdsController addMapping:dsControlKey deviceInfo:deviceInfo]; - - NSMutableDictionary *tempUserMappings = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"Input_ControllerMappings"]]; - [tempUserMappings setValue:[NSArray arrayWithObject:deviceInfo] forKey:dsControlKey]; - [[NSUserDefaults standardUserDefaults] setValue:tempUserMappings forKey:@"Input_ControllerMappings"]; -} - -- (NSString *) parseMappingDisplayString:(NSString *)keyString -{ - NSDictionary *userMappings = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"Input_ControllerMappings"]; - NSArray *mappingList = (NSArray *)[userMappings valueForKey:keyString]; - NSDictionary *mapping = (NSDictionary *)[mappingList objectAtIndex:0]; - NSString *deviceName = (NSString *)[mapping valueForKey:@"deviceName"]; - NSString *elementName = (NSString *)[mapping valueForKey:@"elementName"]; - - NSString *displayString = [NSString stringWithString:deviceName]; - displayString = [displayString stringByAppendingString:@": "]; - displayString = [displayString stringByAppendingString:elementName]; - - return displayString; -} - -- (IBAction) inputButtonSet:(id)sender -{ - NSButton *theButton = (NSButton *)sender; - - if (configInput && lastConfigButton != theButton) - { - [lastConfigButton setState:NSOffState]; - } - - if ([theButton state] == NSOnState) - { - lastConfigButton = theButton; - [configInputList removeAllObjects]; - configInput = [theButton tag]; - } - else - { - [self inputButtonCancelConfig]; - } - -} - -- (void) inputButtonCancelConfig -{ - if (lastConfigButton != nil) - { - [lastConfigButton setState:NSOffState]; - lastConfigButton = nil; - } - - configInput = 0; -} - - (BOOL)acceptsFirstResponder { return YES; @@ -388,56 +326,26 @@ return YES; } -- (void) handleHIDInput:(NSNotification *)aNotification +#pragma mark IBAction Methods + +- (IBAction) inputButtonSet:(id)sender { - if (configInput == 0) + NSButton *theButton = (NSButton *)sender; + + if ([self configInputTargetID] != 0 && lastConfigButton != theButton) { - return; + [lastConfigButton setState:NSOffState]; } - NSArray *inputPropertiesList = (NSArray *)[aNotification object]; - BOOL inputOn = NO; - - for (NSDictionary *inputProperties in inputPropertiesList) + if ([theButton state] == NSOnState) { - NSNumber *onState = (NSNumber *)[inputProperties valueForKey:@"on"]; - if (onState != nil) - { - NSString *deviceCode = (NSString *)[inputProperties valueForKey:@"deviceCode"]; - NSString *elementCode = (NSString *)[inputProperties valueForKey:@"elementCode"]; - NSString *deviceElementCode = [[deviceCode stringByAppendingString:@":"] stringByAppendingString:elementCode]; - NSDate *inputOnDate = [configInputList valueForKey:deviceElementCode]; - - inputOn = [onState boolValue]; - if (inputOn) - { - if (inputOnDate == nil) - { - [configInputList setValue:[NSDate date] forKey:deviceElementCode]; - } - } - else - { - if (inputOnDate != nil) - { - if (([inputOnDate timeIntervalSinceNow] * -1.0) < INPUT_HOLD_TIME) - { - // If the button isn't held for at least INPUT_HOLD_TIME seconds, then reject the input. - [configInputList setValue:nil forKey:deviceElementCode]; - } - else - { - // Add the input mapping. - NSString *deviceName = (NSString *)[inputProperties valueForKey:@"deviceName"]; - NSString *elementName = (NSString *)[inputProperties valueForKey:@"elementName"]; - - [self addMappingById:configInput deviceCode:deviceCode deviceName:deviceName elementCode:elementCode elementName:elementName]; - [self inputButtonCancelConfig]; - break; - } - } - } - } + lastConfigButton = theButton; + [configInputList removeAllObjects]; + [self setConfigInputTargetID:[theButton tag]]; + } + else + { + [self setConfigInputTargetID:0]; } } diff --git a/desmume/src/cocoa/userinterface/preferencesWindowDelegate.h b/desmume/src/cocoa/userinterface/preferencesWindowDelegate.h index efe514ab0..dabd9f08d 100644 --- a/desmume/src/cocoa/userinterface/preferencesWindowDelegate.h +++ b/desmume/src/cocoa/userinterface/preferencesWindowDelegate.h @@ -17,8 +17,8 @@ */ #import +#import "inputPrefsView.h" -@class InputPrefsView; @class CocoaVideoFilter; diff --git a/desmume/src/cocoa/userinterface/preferencesWindowDelegate.mm b/desmume/src/cocoa/userinterface/preferencesWindowDelegate.mm index a0ad3e13f..4af226250 100644 --- a/desmume/src/cocoa/userinterface/preferencesWindowDelegate.mm +++ b/desmume/src/cocoa/userinterface/preferencesWindowDelegate.mm @@ -761,6 +761,16 @@ - (void)windowDidBecomeKey:(NSNotification *)notification { [prefWindowController setContent:bindings]; + + if ([viewInput configInputTargetID] != 0) + { + [[viewInput inputManager] setHidInputTarget:viewInput]; + } +} + +- (void)windowWillClose:(NSNotification *)notification +{ + [viewInput setConfigInputTargetID:0]; } @end