Cocoa Port:

Here it is folks -- A brand new Cocoa port! This is a complete remake from the ground up, and constitutes about a year's worth of coding and testing, so enjoy! This log entry only includes a summary of the new features compared to v0.9.7. Due to the number of changes that have taken place, any bug fixes and developer-related details will not be reported here.

User Experience:
- Added many icons throughout the application to improve the visual appearance and provide easier visual cues.
- Added a toolbar and a sound volume slider to the emulation window.
- Added mouseover tooltips for most of the controls.
- Added the ability to change the emulation window display mode. The user can choose to display only the main screen, only the touch screen, or both screens.
- Added the ability to rotate the emulation window display to any arbitrary rotation angle.
- Added a bilinear filtering option for the display output.
- Added support for using video filters on the display output.
- Added the ability to copy a screenshot to the clipboard using Edit > Copy.
- ROM Info now provides much more ROM information in a better organized panel.
- The emulation window's status bar now gives more user feedback.
- In the emulation window, you can now click close to unload ROMs and quit the application.
- Externally loaded save states now behave more like typical document files: they ask to save upon close/quit, behave properly using Save and Save As, and support revert.

Emulation System:
- A modernized program architecture brings substantial performance improvements, especially on multiprocessor/multicore machines. This brings the Cocoa port much closer to the Windows port in terms of performance.
- Exposed all emulation, firmware, SPU, and SoftRasterizer options in the user interface. This should help users in configuring DeSmuME to work with many ROMs that were unusable before.
- Added support for using BIOS and firmware images.
- Added support for completely disabling GPUs (Tools > View Layers > Main GPU and Tools > View Layers > Sub GPU menu options).
- Added the ability to change the number of 3D rendering threads.
- Added support for using an ADVANsCEne database to autodetect the ROM save type.

Cheat System:
- Added a cheat manager, which allows the user to use cheat codes. DeSmuME internal cheats and Action Replay cheats are both supported.
- Added the ability to run a cheat search.
- Added the ability to import Action Replay cheats from an R4 Cheat database.

Input System:
- Any non-modifier key on the keyboard may now be used for the controller input.
- Added support for using USB HID devices for the controller input. Yes, you can use your favorite gamepads and joysticks now.
- All emulated controls can now be mapped, including Lid and Debug.
- Microphone input is now partially supported. Internal and white noise samples can now be generated for certain ROMs that require microphone input. For now, this should help the user complete certain games that rely heavily on microphone input, such as "The Legend of Zelda: Spirit Tracks".

File Handling:
- Added a file migration assistant to help the user migrate their old files to the current version of DeSmuME.
- Added support for importing and exporting ROM save files in RAW and No$GBA formats.
- Added the Tools > Show Support Folder in Finder menu option, which opens DeSmuME's Application Support folder. This exists as a convenience for Lion users.
- Added new icons for DeSmuME's files.


Note: The XCode Legacy project is now deprecated, and should only be used to make unofficial Tiger builds. Any new builds should use the XCode 3 project.
This commit is contained in:
rogerman 2012-01-20 05:09:13 +00:00
parent 0247b86c2c
commit 0d4811a028
85 changed files with 61103 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,333 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Up</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>126</string>
<key>elementName</key>
<string>Up Arrow</string>
</dict>
</array>
<key>Down</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>125</string>
<key>elementName</key>
<string>Down Arrow</string>
</dict>
</array>
<key>Left</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>123</string>
<key>elementName</key>
<string>Left Arrow</string>
</dict>
</array>
<key>Right</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>124</string>
<key>elementName</key>
<string>Right Arrow</string>
</dict>
</array>
<key>A</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>7</string>
<key>elementName</key>
<string>X</string>
</dict>
</array>
<key>B</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>6</string>
<key>elementName</key>
<string>Z</string>
</dict>
</array>
<key>X</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>1</string>
<key>elementName</key>
<string>S</string>
</dict>
</array>
<key>Y</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>0</string>
<key>elementName</key>
<string>A</string>
</dict>
</array>
<key>L</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>12</string>
<key>elementName</key>
<string>Q</string>
</dict>
</array>
<key>R</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>13</string>
<key>elementName</key>
<string>W</string>
</dict>
</array>
<key>Start</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>36</string>
<key>elementName</key>
<string>Return</string>
</dict>
</array>
<key>Select</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>48</string>
<key>elementName</key>
<string>Tab</string>
</dict>
</array>
<key>Touch</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventMouse</string>
<key>deviceName</key>
<string>Mouse</string>
<key>elementCode</key>
<string>0</string>
<key>elementName</key>
<string>Primary Button</string>
<key>useDeviceValues</key>
<true/>
<key>pointX</key>
<integer>0</integer>
<key>pointY</key>
<real>0</real>
</dict>
</array>
<key>Microphone</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>50</string>
<key>elementName</key>
<string>`</string>
</dict>
</array>
<key>Debug</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>42</string>
<key>elementName</key>
<string>\</string>
</dict>
</array>
<key>Lid</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>51</string>
<key>elementName</key>
<string>Delete (Backspace)</string>
</dict>
</array>
<key>Speed Half</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>27</string>
<key>elementName</key>
<string>-</string>
<key>floatValue</key>
<string>0.5</string>
<key>selector</key>
<string>toggleHoldSpeedHalf:</string>
<key>paramType</key>
<string>floatValue</string>
</dict>
</array>
<key>Speed Double</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>24</string>
<key>elementName</key>
<string>=</string>
<key>floatValue</key>
<integer>2</integer>
<key>selector</key>
<string>toggleHoldSpeedDouble:</string>
<key>paramType</key>
<string>floatValue</string>
</dict>
</array>
<key>HUD</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>4</string>
<key>elementName</key>
<string>H</string>
<key>selector</key>
<string>toggleHoldHUD</string>
</dict>
</array>
<key>Execute</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>117</string>
<key>elementName</key>
<string>Forward Delete</string>
<key>selector</key>
<string>execute</string>
</dict>
</array>
<key>Pause</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>119</string>
<key>elementName</key>
<string>End</string>
<key>selector</key>
<string>pause</string>
</dict>
</array>
<key>Reset</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>121</string>
<key>elementName</key>
<string>Page Down</string>
<key>selector</key>
<string>reset</string>
</dict>
</array>
<key>Mute</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>71</string>
<key>elementName</key>
<string>Numpad Clear</string>
<key>selector</key>
<string>mute</string>
</dict>
</array>
</dict>
</plist>

Binary file not shown.

View File

@ -0,0 +1,474 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>nds</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NintendoDS_ROM.icns</string>
<key>CFBundleTypeName</key>
<string>Nintendo DS ROM</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.rom.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ds.gba</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NintendoGBA_ROM.icns</string>
<key>CFBundleTypeName</key>
<string>Gameboy Advance ROM</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.rom.gba</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dst</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_SaveState.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME Save State</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.savestate</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dsv</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ROMSave.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME ROM Save</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.romsave</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dfc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_FirmwareConfig.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME Firmware Configuration</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.firmwareconfig</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dct</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ROMCheats.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME ROM Cheats</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.romcheats</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>sav</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NoGBA_ROMSave.icns</string>
<key>CFBundleTypeName</key>
<string>No$GBA ROM Save</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>de.emubase.nocash.romsave.gba</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>duc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ActionReplaySave.icns</string>
<key>CFBundleTypeName</key>
<string>Action Replay Save</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.codejunkies.actionreplay.save.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>bin</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_HWImage_NDS.icns</string>
<key>CFBundleTypeName</key>
<string>Nintendo DS Hardware Image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.hwimage.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>xml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ADVANsCEneDatabase.icns</string>
<key>CFBundleTypeName</key>
<string>ADVANsCEne Database</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.advanscene.database.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dat</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_R4CheatDatabase.icns</string>
<key>CFBundleTypeName</key>
<string>R4 Cheats Database</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>net.gbatemp.cheats.database.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>DeSmuME (Debug)</string>
<key>CFBundleIconFile</key>
<string>AppIcon_DeSmuME</string>
<key>CFBundleIdentifier</key>
<string>com.DeSmuME.DeSmuME</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>v0.9.8 (Debug)</string>
<key>CFBundleSignature</key>
<string>DSmM</string>
<key>CFBundleVersion</key>
<string>0.9.8</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright ©2012 DeSmuME Team. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME Save State</string>
<key>UTTypeIconFile</key>
<string>AppIcon_SaveState.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.savestate</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dst</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME ROM Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ROMSave.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.romsave</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dsv</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME Firmware Configuration</string>
<key>UTTypeIconFile</key>
<string>AppIcon_FirmwareConfig.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.firmwareconfig</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dfc</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME ROM Cheats</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ROMCheats.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.romcheats</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dct</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Nintendo DS ROM</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NintendoDS_ROM.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.rom.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>nds</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Gameboy Advance ROM</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NintendoGBA_ROM.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.rom.gba</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>ds.gba</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>No$GBA ROM Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NoGBA_ROMSave.icns</string>
<key>UTTypeIdentifier</key>
<string>de.emubase.nocash.romsave.gba</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>sav</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Action Replay Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ActionReplaySave.icns</string>
<key>UTTypeIdentifier</key>
<string>com.codejunkies.actionreplay.save.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>duc</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Nintendo DS Hardware Image</string>
<key>UTTypeIconFile</key>
<string>AppIcon_HWImage_NDS.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.hwimage.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>bin</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.xml</string>
</array>
<key>UTTypeDescription</key>
<string>ADVANsCEne Database</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ADVANsCEneDatabase.icns</string>
<key>UTTypeIdentifier</key>
<string>com.advanscene.database.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>xml</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>R4 Cheats Database</string>
<key>UTTypeIconFile</key>
<string>AppIcon_R4CheatDatabase.icns</string>
<key>UTTypeIdentifier</key>
<string>net.gbatemp.cheats.database.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dat</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>

View File

@ -0,0 +1,474 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>nds</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NintendoDS_ROM.icns</string>
<key>CFBundleTypeName</key>
<string>Nintendo DS ROM</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.rom.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ds.gba</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NintendoGBA_ROM.icns</string>
<key>CFBundleTypeName</key>
<string>Gameboy Advance ROM</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.rom.gba</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dst</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_SaveState.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME Save State</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.savestate</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dsv</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ROMSave.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME ROM Save</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.romsave</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dfc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_FirmwareConfig.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME Firmware Configuration</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.firmwareconfig</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dct</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ROMCheats.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME ROM Cheats</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.romcheats</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>sav</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NoGBA_ROMSave.icns</string>
<key>CFBundleTypeName</key>
<string>No$GBA ROM Save</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>de.emubase.nocash.romsave.gba</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>duc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ActionReplaySave.icns</string>
<key>CFBundleTypeName</key>
<string>Action Replay Save</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.codejunkies.actionreplay.save.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>bin</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_HWImage_NDS.icns</string>
<key>CFBundleTypeName</key>
<string>Nintendo DS Hardware Image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.hwimage.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>xml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ADVANsCEneDatabase.icns</string>
<key>CFBundleTypeName</key>
<string>ADVANsCEne Database</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.advanscene.database.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dat</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_R4CheatDatabase.icns</string>
<key>CFBundleTypeName</key>
<string>R4 Cheats Database</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>net.gbatemp.cheats.database.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>DeSmuME</string>
<key>CFBundleIconFile</key>
<string>AppIcon_DeSmuME</string>
<key>CFBundleIdentifier</key>
<string>com.DeSmuME.DeSmuME</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>v0.9.8</string>
<key>CFBundleSignature</key>
<string>DSmM</string>
<key>CFBundleVersion</key>
<string>0.9.8</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright ©2012 DeSmuME Team. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME Save State</string>
<key>UTTypeIconFile</key>
<string>AppIcon_SaveState.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.savestate</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dst</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME ROM Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ROMSave.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.romsave</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dsv</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME Firmware Configuration</string>
<key>UTTypeIconFile</key>
<string>AppIcon_FirmwareConfig.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.firmwareconfig</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dfc</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME ROM Cheats</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ROMCheats.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.romcheats</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dct</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Nintendo DS ROM</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NintendoDS_ROM.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.rom.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>nds</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Gameboy Advance ROM</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NintendoGBA_ROM.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.rom.gba</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>ds.gba</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>No$GBA ROM Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NoGBA_ROMSave.icns</string>
<key>UTTypeIdentifier</key>
<string>de.emubase.nocash.romsave.gba</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>sav</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Action Replay Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ActionReplaySave.icns</string>
<key>UTTypeIdentifier</key>
<string>com.codejunkies.actionreplay.save.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>duc</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Nintendo DS Hardware Image</string>
<key>UTTypeIconFile</key>
<string>AppIcon_HWImage_NDS.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.hwimage.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>bin</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.xml</string>
</array>
<key>UTTypeDescription</key>
<string>ADVANsCEne Database</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ADVANsCEneDatabase.icns</string>
<key>UTTypeIdentifier</key>
<string>com.advanscene.database.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>xml</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>R4 Cheats Database</string>
<key>UTTypeIconFile</key>
<string>AppIcon_R4CheatDatabase.icns</string>
<key>UTTypeIdentifier</key>
<string>net.gbatemp.cheats.database.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dat</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>

View File

@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>12</key>
<string>Q</string>
<key>13</key>
<string>W</string>
<key>14</key>
<string>E</string>
<key>15</key>
<string>R</string>
<key>17</key>
<string>T</string>
<key>16</key>
<string>Y</string>
<key>32</key>
<string>U</string>
<key>34</key>
<string>I</string>
<key>31</key>
<string>O</string>
<key>35</key>
<string>P</string>
<key>0</key>
<string>A</string>
<key>1</key>
<string>S</string>
<key>2</key>
<string>D</string>
<key>3</key>
<string>F</string>
<key>5</key>
<string>G</string>
<key>4</key>
<string>H</string>
<key>38</key>
<string>J</string>
<key>40</key>
<string>K</string>
<key>37</key>
<string>L</string>
<key>6</key>
<string>Z</string>
<key>7</key>
<string>X</string>
<key>8</key>
<string>C</string>
<key>9</key>
<string>V</string>
<key>11</key>
<string>B</string>
<key>45</key>
<string>N</string>
<key>46</key>
<string>M</string>
<key>18</key>
<string>1</string>
<key>19</key>
<string>2</string>
<key>20</key>
<string>3</string>
<key>21</key>
<string>4</string>
<key>23</key>
<string>5</string>
<key>22</key>
<string>6</string>
<key>26</key>
<string>7</string>
<key>28</key>
<string>8</string>
<key>25</key>
<string>9</string>
<key>29</key>
<string>0</string>
<key>122</key>
<string>F1</string>
<key>120</key>
<string>F2</string>
<key>99</key>
<string>F3</string>
<key>118</key>
<string>F4</string>
<key>96</key>
<string>F5</string>
<key>97</key>
<string>F6</string>
<key>98</key>
<string>F7</string>
<key>100</key>
<string>F8</string>
<key>101</key>
<string>F9</string>
<key>109</key>
<string>F10</string>
<key>103</key>
<string>F11</string>
<key>111</key>
<string>F12</string>
<key>105</key>
<string>F13</string>
<key>107</key>
<string>F14</string>
<key>113</key>
<string>F15</string>
<key>106</key>
<string>F16</string>
<key>64</key>
<string>F17</string>
<key>79</key>
<string>F18</string>
<key>80</key>
<string>F19</string>
<key>50</key>
<string>`</string>
<key>27</key>
<string>-</string>
<key>24</key>
<string>=</string>
<key>51</key>
<string>Delete (Backspace)</string>
<key>48</key>
<string>Tab</string>
<key>33</key>
<string>[</string>
<key>30</key>
<string>]</string>
<key>42</key>
<string>\</string>
<key>41</key>
<string>; (Semicolon)</string>
<key>39</key>
<string>&apos; (Quote)</string>
<key>36</key>
<string>Return</string>
<key>43</key>
<string>, (Comma)</string>
<key>47</key>
<string>. (Period)</string>
<key>44</key>
<string>/</string>
<key>49</key>
<string>Space</string>
<key>115</key>
<string>Home</string>
<key>119</key>
<string>End</string>
<key>116</key>
<string>Page Up</string>
<key>121</key>
<string>Page Down</string>
<key>117</key>
<string>Forward Delete</string>
<key>126</key>
<string>Up Arrow</string>
<key>125</key>
<string>Down Arrow</string>
<key>123</key>
<string>Left Arrow</string>
<key>124</key>
<string>Right Arrow</string>
<key>82</key>
<string>NumPad 0</string>
<key>83</key>
<string>NumPad 1</string>
<key>84</key>
<string>NumPad 2</string>
<key>85</key>
<string>NumPad 3</string>
<key>86</key>
<string>NumPad 4</string>
<key>87</key>
<string>NumPad 5</string>
<key>88</key>
<string>NumPad 6</string>
<key>89</key>
<string>NumPad 7</string>
<key>91</key>
<string>NumPad 8</string>
<key>92</key>
<string>NumPad 9</string>
<key>71</key>
<string>NumPad Clear</string>
<key>81</key>
<string>NumPad =</string>
<key>75</key>
<string>NumPad /</string>
<key>67</key>
<string>NumPad *</string>
<key>78</key>
<string>NumPad -</string>
<key>69</key>
<string>NumPad +</string>
<key>65</key>
<string>NumPad .</string>
<key>76</key>
<string>NumPad Enter</string>
<key>53</key>
<string>Escape</string>
</dict>
</plist>

View File

@ -0,0 +1,164 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include "../cheatSystem.h"
@class CocoaDSCore;
/********************************************************************************************
CocoaDSCheatItem - OBJECTIVE-C CLASS
This is an Objective-C wrapper class for DeSmuME's cheat item struct.
The cheat item data is not freed upon release of this object. This is by design.
Thread Safety:
Assume that all methods are not thread-safe. This was done for performance
reasons. The caller of this class' methods is expected to handle thread safety.
********************************************************************************************/
@interface CocoaDSCheatItem : NSObject
{
CHEATS_LIST *data;
CHEATS_LIST *internalData;
BOOL willAdd;
pthread_mutex_t mutexData;
CocoaDSCheatItem *workingCopy;
CocoaDSCheatItem *parent;
}
@property (assign) CHEATS_LIST *data;
@property (assign) BOOL willAdd;
@property (assign, nonatomic) BOOL enabled;
@property (assign, nonatomic) NSInteger cheatType;
@property (assign, nonatomic) NSImage *cheatTypeIcon;
@property (assign, nonatomic) BOOL isSupportedCheatType;
@property (assign, nonatomic) NSInteger freezeType;
@property (assign, nonatomic) NSString *description;
@property (assign, nonatomic) NSUInteger codeCount;
@property (assign, nonatomic) NSString *code;
@property (assign, nonatomic) UInt8 bytes;
@property (assign, nonatomic) UInt32 memAddress;
@property (assign, nonatomic) NSString *memAddressString;
@property (assign, nonatomic) NSString *memAddressSixDigitString;
@property (assign, nonatomic) SInt64 value;
@property (readonly) CocoaDSCheatItem *workingCopy;
@property (assign) CocoaDSCheatItem *parent;
- (id) initWithCheatData:(CHEATS_LIST *)cheatData;
- (BOOL) retainData;
- (char *) descriptionCString;
- (void) update;
- (CocoaDSCheatItem *) createWorkingCopy;
- (void) destroyWorkingCopy;
- (void) mergeFromWorkingCopy;
- (void) mergeToParent;
- (void) setDataWithDictionary:(NSDictionary *)dataDict;
- (NSDictionary *) dataDictionary;
@end
/********************************************************************************************
CocoaDSCheatManager - OBJECTIVE-C CLASS
This is an Objective-C wrapper class for DeSmuME's cheat list class.
Thread Safety:
All methods are thread-safe.
********************************************************************************************/
@interface CocoaDSCheatManager : NSObject
{
CHEATS *listData;
NSMutableArray *list;
CocoaDSCore *cdsCore;
NSUInteger untitledCount;
NSString *dbTitle;
NSString *dbDate;
}
@property (readonly) CHEATS *listData;
@property (readonly) NSMutableArray *list;
@property (assign) CocoaDSCore *cdsCore;
@property (assign) NSUInteger untitledCount;
@property (assign) NSString *dbTitle;
@property (assign) NSString *dbDate;
- (id) initWithCore:(CocoaDSCore *)core;
- (id) initWithURL:(CocoaDSCore *)core fileURL:(NSURL *)fileURL;
- (id) initWithExistingList:(CocoaDSCore *)core listData:(CHEATS *)cheatList;
- (id) initWithURL:(CocoaDSCore *)core fileURL:(NSURL *)fileURL listData:(CHEATS *)cheatList;
- (BOOL) add:(CocoaDSCheatItem *)cheatItem;
- (void) remove:(CocoaDSCheatItem *)cheatItem;
- (BOOL) update:(CocoaDSCheatItem *)cheatItem;
- (BOOL) save;
- (NSMutableArray *) cheatListFromDatabase:(NSURL *)fileURL errorCode:(NSInteger *)error;
- (void) applyInternalCheat:(CocoaDSCheatItem *)cheatItem;
+ (void) setMasterCheatList:(CocoaDSCheatManager *)cheatListManager;
+ (void) applyInternalCheatWithItem:(CocoaDSCheatItem *)cheatItem;
+ (void) applyInternalCheatWithAddress:(UInt32)address value:(UInt32)value bytes:(NSUInteger)bytes;
+ (NSMutableArray *) cheatListWithListObject:(CHEATS *)cheatList;
+ (NSMutableArray *) cheatListWithItemStructArray:(CHEATS_LIST *)cheatItemArray count:(NSUInteger)itemCount;
+ (NSMutableDictionary *) cheatItemWithType:(NSInteger)cheatTypeID description:(NSString *)description;
@end
@interface CocoaDSCheatSearch : NSObject
{
CHEATSEARCH *listData;
NSMutableArray *addressList;
CocoaDSCore *cdsCore;
NSUInteger searchCount;
}
@property (readonly) CHEATSEARCH *listData;
@property (readonly) NSMutableArray *addressList;
@property (assign) CocoaDSCore *cdsCore;
@property (readonly) NSUInteger searchCount;
- (id) initWithCore:(CocoaDSCore *)core;
- (NSUInteger) runExactValueSearch:(NSInteger)value byteSize:(UInt8)byteSize signType:(NSInteger)signType;
- (void) runExactValueSearchOnThread:(id)object;
- (NSUInteger) runComparativeSearch:(NSInteger)typeID byteSize:(UInt8)byteSize signType:(NSInteger)signType;
- (void) runComparativeSearchOnThread:(id)object;
- (void) reset;
+ (NSMutableArray *) addressListWithListObject:(CHEATSEARCH *)addressList maxItems:(NSUInteger)maxItemCount;
@end
@interface CocoaDSCheatSearchParams : NSObject
{
NSInteger comparativeSearchType;
NSInteger value;
UInt8 byteSize;
NSInteger signType;
}
@property (assign) NSInteger comparativeSearchType;
@property (assign) NSInteger value;
@property (assign) UInt8 byteSize;
@property (assign) NSInteger signType;
@end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include <pthread.h>
#include <libkern/OSAtomic.h>
#import "cocoa_util.h"
@class CocoaDSRom;
@class CocoaDSController;
@class CocoaDSFirmware;
@class CocoaDSOutput;
typedef struct
{
void *cdsCore;
int state;
bool isFrameSkipEnabled;
unsigned int frameCount;
unsigned int framesToSkip;
NSTimeInterval calcTimeBudget;
bool exitThread;
pthread_mutex_t *mutexCoreExecute;
pthread_mutex_t mutexThreadExecute;
pthread_cond_t condThreadExecute;
} CoreThreadParam;
@interface CocoaDSCore : CocoaDSThread
{
CocoaDSController *cdsController;
CocoaDSFirmware *cdsFirmware;
NSMutableArray *cdsOutputList;
pthread_t coreThread;
CoreThreadParam threadParam;
NSInteger prevCoreState;
BOOL isSpeedLimitEnabled;
CGFloat speedScalar;
NSUInteger emulationFlags;
BOOL emuFlagAdvancedBusLevelTiming;
BOOL emuFlagUseExternalBios;
BOOL emuFlagEmulateBiosInterrupts;
BOOL emuFlagPatchDelayLoop;
BOOL emuFlagUseExternalFirmware;
BOOL emuFlagFirmwareBoot;
BOOL emuFlagDebugConsole;
BOOL emuFlagEmulateEnsata;
pthread_mutex_t *mutexCoreExecute;
OSSpinLock spinlockMasterExecute;
OSSpinLock spinlockExecutionChange;
OSSpinLock spinlockCheatEnableFlag;
OSSpinLock spinlockEmulationFlags;
}
@property (assign) CocoaDSController *cdsController;
@property (assign) CocoaDSFirmware *cdsFirmware;
@property (assign) NSMutableArray *cdsOutputList;
@property (assign) BOOL masterExecute;
@property (assign) BOOL isFrameSkipEnabled;
@property (assign) NSInteger coreState;
@property (assign) BOOL isSpeedLimitEnabled;
@property (assign) BOOL isCheatingEnabled;
@property (assign) CGFloat speedScalar;
@property (assign) NSUInteger emulationFlags;
@property (assign) BOOL emuFlagAdvancedBusLevelTiming;
@property (assign) BOOL emuFlagUseExternalBios;
@property (assign) BOOL emuFlagEmulateBiosInterrupts;
@property (assign) BOOL emuFlagPatchDelayLoop;
@property (assign) BOOL emuFlagUseExternalFirmware;
@property (assign) BOOL emuFlagFirmwareBoot;
@property (assign) BOOL emuFlagDebugConsole;
@property (assign) BOOL emuFlagEmulateEnsata;
@property (assign) NSURL *arm9ImageURL;
@property (assign) NSURL *arm7ImageURL;
@property (assign) NSURL *firmwareImageURL;
@property (readonly) pthread_mutex_t *mutexCoreExecute;
+ (BOOL) startupCore;
+ (void) shutdownCore;
+ (BOOL) isCoreStarted;
- (BOOL) ejectCardFlag;
- (void) setEjectCardFlag;
- (void) toggleEjectCard;
- (void) changeRomSaveType:(NSInteger)saveTypeID;
- (void) changeExecutionSpeed;
- (void) restoreCoreState;
- (void) reset;
- (void) addOutput:(CocoaDSOutput *)theOutput;
- (void) removeOutput:(CocoaDSOutput *)theOutput;
- (void) removeAllOutputs;
@end
void* RunCoreThread(void *arg);
void CoreFrameSkip(NSTimeInterval timeBudget, NSTimeInterval timeRemaining, unsigned int *outFramesToSkip);

View File

@ -0,0 +1,709 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "cocoa_core.h"
#import "cocoa_input.h"
#import "cocoa_firmware.h"
#import "cocoa_globals.h"
#import "cocoa_output.h"
#import "cocoa_rom.h"
#import "cocoa_util.h"
#include "../NDSSystem.h"
#undef BOOL
//accessed from other files
volatile bool execute = true;
@implementation CocoaDSCore
@synthesize cdsController;
@synthesize cdsFirmware;
@synthesize cdsOutputList;
@dynamic masterExecute;
@dynamic isFrameSkipEnabled;
@dynamic coreState;
@dynamic isSpeedLimitEnabled;
@dynamic isCheatingEnabled;
@dynamic speedScalar;
@dynamic emulationFlags;
@synthesize emuFlagAdvancedBusLevelTiming;
@synthesize emuFlagUseExternalBios;
@synthesize emuFlagEmulateBiosInterrupts;
@synthesize emuFlagPatchDelayLoop;
@synthesize emuFlagUseExternalFirmware;
@synthesize emuFlagFirmwareBoot;
@synthesize emuFlagDebugConsole;
@synthesize emuFlagEmulateEnsata;
@dynamic arm9ImageURL;
@dynamic arm7ImageURL;
@dynamic firmwareImageURL;
@synthesize mutexCoreExecute;
static BOOL isCoreStarted = NO;
- (id)init
{
self = [super init];
if(self == nil)
{
return self;
}
cdsController = nil;
cdsFirmware = nil;
cdsOutputList = [[NSMutableArray alloc] initWithCapacity:32];
emulationFlags = EMULATION_ADVANCED_BUS_LEVEL_TIMING_MASK;
emuFlagAdvancedBusLevelTiming = YES;
emuFlagUseExternalBios = NO;
emuFlagEmulateBiosInterrupts = NO;
emuFlagPatchDelayLoop = NO;
emuFlagUseExternalFirmware = NO;
emuFlagFirmwareBoot = NO;
emuFlagDebugConsole = NO;
emuFlagEmulateEnsata = NO;
mutexCoreExecute = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutexCoreExecute, NULL);
spinlockMasterExecute = OS_SPINLOCK_INIT;
spinlockExecutionChange = OS_SPINLOCK_INIT;
spinlockCheatEnableFlag = OS_SPINLOCK_INIT;
spinlockEmulationFlags = OS_SPINLOCK_INIT;
isSpeedLimitEnabled = YES;
speedScalar = SPEED_SCALAR_NORMAL;
prevCoreState = CORESTATE_PAUSE;
threadParam.cdsCore = self;
threadParam.state = CORESTATE_PAUSE;
threadParam.isFrameSkipEnabled = true;
threadParam.frameCount = 0;
threadParam.framesToSkip = 0;
threadParam.calcTimeBudget = (NSTimeInterval)(DS_SECONDS_PER_FRAME / speedScalar);
threadParam.exitThread = false;
threadParam.mutexCoreExecute = mutexCoreExecute;
pthread_mutex_init(&threadParam.mutexThreadExecute, NULL);
pthread_cond_init(&threadParam.condThreadExecute, NULL);
pthread_create(&coreThread, NULL, &RunCoreThread, &threadParam);
return self;
}
- (void)dealloc
{
[self setCoreState:CORESTATE_PAUSE];
// Exit the thread.
if (self.thread != nil)
{
self.threadExit = YES;
// Wait until the thread has shut down.
while (self.thread != nil)
{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
}
pthread_mutex_lock(&threadParam.mutexThreadExecute);
threadParam.exitThread = true;
pthread_cond_signal(&threadParam.condThreadExecute);
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
pthread_join(coreThread, NULL);
coreThread = nil;
pthread_mutex_destroy(&threadParam.mutexThreadExecute);
pthread_cond_destroy(&threadParam.condThreadExecute);
pthread_mutex_destroy(self.mutexCoreExecute);
free(self.mutexCoreExecute);
mutexCoreExecute = nil;
[super dealloc];
}
+ (BOOL) startupCore
{
NSInteger result = -1;
if (isCoreStarted)
{
return isCoreStarted;
}
result = NDS_Init();
if (result == -1)
{
isCoreStarted = NO;
return isCoreStarted;
}
isCoreStarted = YES;
return isCoreStarted;
}
+ (void) shutdownCore
{
if (isCoreStarted)
{
NDS_DeInit();
isCoreStarted = NO;
}
}
+ (BOOL) isCoreStarted
{
return isCoreStarted;
}
- (void) setMasterExecute:(BOOL)theState
{
OSSpinLockLock(&spinlockMasterExecute);
if (theState)
{
execute = true;
}
else
{
execute = false;
}
OSSpinLockUnlock(&spinlockMasterExecute);
}
- (BOOL) masterExecute
{
BOOL theState = NO;
OSSpinLockLock(&spinlockMasterExecute);
if (execute)
{
theState = YES;
}
OSSpinLockUnlock(&spinlockMasterExecute);
return theState;
}
- (void) setIsFrameSkipEnabled:(BOOL)theState
{
pthread_mutex_lock(&threadParam.mutexThreadExecute);
if (theState)
{
threadParam.isFrameSkipEnabled = true;
}
else
{
threadParam.isFrameSkipEnabled = false;
}
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
}
- (BOOL) isFrameSkipEnabled
{
BOOL theState = NO;
pthread_mutex_lock(&threadParam.mutexThreadExecute);
bool cState = threadParam.isFrameSkipEnabled;
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
if (cState)
{
theState = YES;
}
return theState;
}
- (void) setSpeedScalar:(CGFloat)scalar
{
OSSpinLockLock(&spinlockExecutionChange);
speedScalar = scalar;
OSSpinLockUnlock(&spinlockExecutionChange);
[self changeExecutionSpeed];
}
- (CGFloat) speedScalar
{
OSSpinLockLock(&spinlockExecutionChange);
CGFloat scalar = speedScalar;
OSSpinLockUnlock(&spinlockExecutionChange);
return scalar;
}
- (void) setIsSpeedLimitEnabled:(BOOL)theState
{
OSSpinLockLock(&spinlockExecutionChange);
isSpeedLimitEnabled = theState;
OSSpinLockUnlock(&spinlockExecutionChange);
[self changeExecutionSpeed];
}
- (BOOL) isSpeedLimitEnabled
{
OSSpinLockLock(&spinlockExecutionChange);
BOOL enabled = isSpeedLimitEnabled;
OSSpinLockUnlock(&spinlockExecutionChange);
return enabled;
}
- (void) setIsCheatingEnabled:(BOOL)theState
{
OSSpinLockLock(&spinlockCheatEnableFlag);
if (theState)
{
CommonSettings.cheatsDisable = false;
}
else
{
CommonSettings.cheatsDisable = true;
}
OSSpinLockUnlock(&spinlockCheatEnableFlag);
}
- (BOOL) isCheatingEnabled
{
BOOL theState = YES;
OSSpinLockLock(&spinlockCheatEnableFlag);
if (CommonSettings.cheatsDisable)
{
theState = NO;
}
OSSpinLockUnlock(&spinlockCheatEnableFlag);
return theState;
}
- (void) setEmulationFlags:(NSUInteger)theFlags
{
OSSpinLockLock(&spinlockEmulationFlags);
emulationFlags = theFlags;
OSSpinLockUnlock(&spinlockEmulationFlags);
pthread_mutex_lock(self.mutexCoreExecute);
if (theFlags & EMULATION_ADVANCED_BUS_LEVEL_TIMING_MASK)
{
self.emuFlagAdvancedBusLevelTiming = YES;
CommonSettings.advanced_timing = true;
}
else
{
self.emuFlagAdvancedBusLevelTiming = NO;
CommonSettings.advanced_timing = false;
}
if (theFlags & EMULATION_ENSATA_MASK)
{
self.emuFlagEmulateEnsata = YES;
CommonSettings.EnsataEmulation = true;
}
else
{
self.emuFlagEmulateEnsata = NO;
CommonSettings.EnsataEmulation = false;
}
if (theFlags & EMULATION_USE_EXTERNAL_BIOS_MASK)
{
self.emuFlagUseExternalBios = YES;
CommonSettings.UseExtBIOS = true;
}
else
{
self.emuFlagUseExternalBios = NO;
CommonSettings.UseExtBIOS = false;
}
if (theFlags & EMULATION_BIOS_SWI_MASK)
{
self.emuFlagEmulateBiosInterrupts = YES;
CommonSettings.SWIFromBIOS = true;
}
else
{
self.emuFlagEmulateBiosInterrupts = NO;
CommonSettings.SWIFromBIOS = false;
}
if (theFlags & EMULATION_PATCH_DELAY_LOOP_MASK)
{
self.emuFlagPatchDelayLoop = YES;
CommonSettings.PatchSWI3 = true;
}
else
{
self.emuFlagPatchDelayLoop = NO;
CommonSettings.PatchSWI3 = false;
}
if (theFlags & EMULATION_USE_EXTERNAL_FIRMWARE_MASK)
{
self.emuFlagUseExternalFirmware = YES;
CommonSettings.UseExtFirmware = true;
}
else
{
self.emuFlagUseExternalFirmware = NO;
CommonSettings.UseExtFirmware = false;
}
if (theFlags & EMULATION_BOOT_FROM_FIRMWARE_MASK)
{
self.emuFlagFirmwareBoot = YES;
CommonSettings.BootFromFirmware = true;
}
else
{
self.emuFlagFirmwareBoot = NO;
CommonSettings.BootFromFirmware = false;
}
if (theFlags & EMULATION_DEBUG_CONSOLE_MASK)
{
self.emuFlagDebugConsole = YES;
CommonSettings.DebugConsole = true;
}
else
{
self.emuFlagDebugConsole = NO;
CommonSettings.DebugConsole = false;
}
pthread_mutex_unlock(self.mutexCoreExecute);
}
- (NSUInteger) emulationFlags
{
OSSpinLockLock(&spinlockEmulationFlags);
NSUInteger theFlags = emulationFlags;
OSSpinLockUnlock(&spinlockEmulationFlags);
return theFlags;
}
- (void) setCoreState:(NSInteger)coreState
{
if (threadParam.state == CORESTATE_PAUSE)
{
prevCoreState = CORESTATE_PAUSE;
}
else
{
prevCoreState = CORESTATE_EXECUTE;
}
pthread_mutex_lock(&threadParam.mutexThreadExecute);
threadParam.state = coreState;
pthread_cond_signal(&threadParam.condThreadExecute);
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
}
- (NSInteger) coreState
{
pthread_mutex_lock(&threadParam.mutexThreadExecute);
NSInteger theState = threadParam.state;
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
return theState;
}
- (void) setArm9ImageURL:(NSURL *)fileURL
{
if (fileURL != nil)
{
strlcpy(CommonSettings.ARM9BIOS, [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding], sizeof(CommonSettings.ARM9BIOS));
}
else
{
memset(CommonSettings.ARM9BIOS, 0, sizeof(CommonSettings.ARM9BIOS));
}
}
- (NSURL *) arm9ImageURL
{
return [NSURL fileURLWithPath:[NSString stringWithCString:CommonSettings.ARM9BIOS encoding:NSUTF8StringEncoding]];
}
- (void) setArm7ImageURL:(NSURL *)fileURL
{
if (fileURL != nil)
{
strlcpy(CommonSettings.ARM7BIOS, [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding], sizeof(CommonSettings.ARM7BIOS));
}
else
{
memset(CommonSettings.ARM7BIOS, 0, sizeof(CommonSettings.ARM7BIOS));
}
}
- (NSURL *) arm7ImageURL
{
return [NSURL fileURLWithPath:[NSString stringWithCString:CommonSettings.ARM7BIOS encoding:NSUTF8StringEncoding]];
}
- (void) setFirmwareImageURL:(NSURL *)fileURL
{
if (fileURL != nil)
{
strlcpy(CommonSettings.Firmware, [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding], sizeof(CommonSettings.Firmware));
}
else
{
memset(CommonSettings.Firmware, 0, sizeof(CommonSettings.Firmware));
}
}
- (NSURL *) firmwareImageURL
{
return [NSURL fileURLWithPath:[NSString stringWithCString:CommonSettings.Firmware encoding:NSUTF8StringEncoding]];
}
- (void) setEjectCardFlag
{
if (nds.cardEjected)
{
self.emulationFlags = self.emulationFlags | EMULATION_CARD_EJECT_MASK;
return;
}
self.emulationFlags = self.emulationFlags & ~EMULATION_CARD_EJECT_MASK;
}
- (BOOL) ejectCardFlag
{
[self setEjectCardFlag];
if (nds.cardEjected)
{
return YES;
}
return NO;
}
- (void) toggleEjectCard
{
NDS_ToggleCardEject();
[self setEjectCardFlag];
}
- (void) changeRomSaveType:(NSInteger)saveTypeID
{
pthread_mutex_lock(self.mutexCoreExecute);
[CocoaDSRom changeRomSaveType:saveTypeID];
pthread_mutex_unlock(self.mutexCoreExecute);
}
- (void) changeExecutionSpeed
{
if (self.isSpeedLimitEnabled)
{
CGFloat theSpeed = self.speedScalar;
if(theSpeed <= SPEED_SCALAR_MIN)
{
theSpeed = SPEED_SCALAR_MIN;
}
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
threadParam.calcTimeBudget = (NSTimeInterval)(DS_SECONDS_PER_FRAME / theSpeed);
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
}
else
{
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
threadParam.calcTimeBudget = 0.0;
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
}
}
- (void) restoreCoreState
{
[self setCoreState:prevCoreState];
}
- (void) reset
{
[self setCoreState:CORESTATE_PAUSE];
pthread_mutex_lock(&threadParam.mutexThreadExecute);
NDS_Reset();
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
[self restoreCoreState];
self.masterExecute = YES;
}
- (void) addOutput:(CocoaDSOutput *)theOutput
{
[self.cdsOutputList addObject:theOutput];
}
- (void) removeOutput:(CocoaDSOutput *)theOutput
{
[self.cdsOutputList removeObject:theOutput];
}
- (void) removeAllOutputs
{
[self.cdsOutputList removeAllObjects];
}
- (void) runThread:(id)object
{
[CocoaDSCore startupCore];
[super runThread:object];
[CocoaDSCore shutdownCore];
}
@end
void* RunCoreThread(void *arg)
{
CoreThreadParam *param = (CoreThreadParam *)arg;
CocoaDSCore *cdsCore = (CocoaDSCore *)param->cdsCore;
NSMutableArray *cdsOutputList = [cdsCore cdsOutputList];
NSDate *loopStartDate = nil;
do
{
loopStartDate = [[NSDate alloc] init];
pthread_mutex_lock(&param->mutexThreadExecute);
while (!(param->state == CORESTATE_EXECUTE && execute && !param->exitThread))
{
[loopStartDate release];
pthread_cond_wait(&param->condThreadExecute, &param->mutexThreadExecute);
loopStartDate = [[NSDate alloc] init];
}
if (param->exitThread)
{
[loopStartDate release];
break;
}
// Get the user's input, execute a single emulation frame, and generate
// the frame output.
[cdsCore.cdsController update];
NDS_beginProcessingInput();
// Shouldn't need to do any special processing steps in between.
// We'll just jump directly to ending the input processing.
NDS_endProcessingInput();
for(CocoaDSOutput *cdsOutput in cdsOutputList)
{
pthread_mutex_lock(cdsOutput.mutexOutputFrame);
}
// Execute the frame and increment the frame counter.
pthread_mutex_lock(param->mutexCoreExecute);
NDS_exec<false>();
pthread_mutex_unlock(param->mutexCoreExecute);
if (param->framesToSkip == 0 || !param->isFrameSkipEnabled)
{
param->frameCount++;
}
for(CocoaDSOutput *cdsOutput in cdsOutputList)
{
if (param->isFrameSkipEnabled && param->framesToSkip > 0 && [cdsOutput isMemberOfClass:[CocoaDSDisplay class]])
{
pthread_mutex_unlock(cdsOutput.mutexOutputFrame);
continue;
}
[cdsOutput doCoreEmuFrame];
pthread_mutex_unlock(cdsOutput.mutexOutputFrame);
}
// Determine the number of frames to skip based on how much time "debt"
// we owe on timeBudget.
if (param->isFrameSkipEnabled)
{
CoreFrameSkip(param->calcTimeBudget, param->calcTimeBudget + [loopStartDate timeIntervalSinceNow], &param->framesToSkip);
}
// If there is any time left in the loop, go ahead and pad it.
NSTimeInterval timePad = param->calcTimeBudget + [loopStartDate timeIntervalSinceNow];
pthread_mutex_unlock(&param->mutexThreadExecute);
if(timePad > 0.0)
{
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4) // Code for Mac OS X 10.4 and earlier
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:timePad]];
#else // Code for Mac OS X 10.5 and later
[NSThread sleepForTimeInterval:timePad];
#endif
}
[loopStartDate release];
} while (!param->exitThread);
return nil;
}
void CoreFrameSkip(NSTimeInterval timeBudget, NSTimeInterval timeRemaining, unsigned int *outFramesToSkip)
{
if (*outFramesToSkip > 0)
{
NDS_SkipNextFrame();
(*outFramesToSkip)--;
}
else
{
if (timeRemaining <= 0.0)
{
if (timeBudget > 0.0)
{
*outFramesToSkip = (unsigned int)( ((-timeRemaining * FRAME_SKIP_AGGRESSIVENESS)/timeBudget) + FRAME_SKIP_BIAS );
}
else
{
*outFramesToSkip = (unsigned int)( ((-timeRemaining * FRAME_SKIP_AGGRESSIVENESS * 100.0)/DS_SECONDS_PER_FRAME) + FRAME_SKIP_BIAS );
}
if (*outFramesToSkip > (unsigned int)MAX_FRAME_SKIP)
{
*outFramesToSkip = (unsigned int)MAX_FRAME_SKIP;
}
}
}
}

View File

@ -0,0 +1,60 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
/********************************************************************************************
CocoaDSFirmware - OBJECTIVE-C CLASS
This is an Objective-C wrapper class for DeSmuME's firmware struct.
If this object is instantiated through any init method other than initWithFirmwareData:,
this object allocate memory for its own internal firmware struct. This memory is then
freed upon the release of this object.
If this object is instantiated using initWithFirmwareData:, or if a firmware struct is
assigned through the data property, the firmware struct is not freed upon the release
of this object. This is by design.
Thread Safety:
All methods are thread-safe.
********************************************************************************************/
@interface CocoaDSFirmware : NSObject
{
struct NDS_fw_config_data *data;
struct NDS_fw_config_data *internalData;
NSInteger birth_year;
pthread_mutex_t mutex;
}
@property (assign) struct NDS_fw_config_data *data;
@property (assign) NSInteger consoleType;
@property (assign) NSString *nickname;
@property (assign) NSString *message;
@property (assign) NSInteger favoriteColor;
@property (assign) NSDate *birthday;
@property (assign) NSInteger language;
- (id) initWithDictionary:(NSDictionary *)dataDict;
- (id) initWithFirmwareData:(struct NDS_fw_config_data *)fwData;
- (void) update;
- (void) setDataWithDictionary:(NSDictionary *)fwDataDict;
- (NSDictionary *) dataDictionary;
@end

View File

@ -0,0 +1,307 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "cocoa_firmware.h"
#include "../NDSSystem.h"
@implementation CocoaDSFirmware
@synthesize data;
@dynamic consoleType;
@dynamic nickname;
@dynamic message;
@dynamic favoriteColor;
@dynamic birthday;
@dynamic language;
- (id)init
{
return [self initWithDictionary:nil];
}
- (id) initWithDictionary:(NSDictionary *)fwDataDict
{
self = [super init];
if (self == nil)
{
return self;
}
pthread_mutex_init(&mutex, NULL);
// Allocate our own firmware struct since we weren't provided with one.
internalData = (struct NDS_fw_config_data *)malloc(sizeof(struct NDS_fw_config_data));
if (internalData == nil)
{
pthread_mutex_destroy(&mutex);
[self release];
return nil;
}
NDS_FillDefaultFirmwareConfigData(internalData);
data = internalData;
[self setDataWithDictionary:fwDataDict];
return self;
}
- (id) initWithFirmwareData:(struct NDS_fw_config_data *)fwData
{
self = [super init];
if (self == nil)
{
return self;
}
pthread_mutex_init(&mutex, NULL);
if (fwData == nil)
{
pthread_mutex_destroy(&mutex);
[self release];
return nil;
}
// Set birth_year to the current year.
NSDate *now = [[NSDate alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"Y"];
birth_year = [[dateFormatter stringFromDate:now] integerValue];
[dateFormatter release];
[now release];
internalData = NULL;
data = fwData;
return self;
}
- (void)dealloc
{
free(internalData);
internalData = NULL;
pthread_mutex_destroy(&mutex);
[super dealloc];
}
- (void) setConsoleType:(NSInteger)theType
{
pthread_mutex_lock(&mutex);
data->ds_type = (NDS_CONSOLE_TYPE)theType;
pthread_mutex_unlock(&mutex);
}
- (NSInteger) consoleType
{
pthread_mutex_lock(&mutex);
NSInteger theType = data->ds_type;
pthread_mutex_unlock(&mutex);
return theType;
}
- (void) setNickname:(NSString *)theNickname
{
if (theNickname == nil)
{
return;
}
pthread_mutex_lock(&mutex);
NSRange characterRange = {0, [theNickname length]};
if (characterRange.length > MAX_FW_NICKNAME_LENGTH)
{
characterRange.length = MAX_FW_NICKNAME_LENGTH;
}
[theNickname getBytes:&data->nickname[0]
maxLength:(sizeof(UInt16) * characterRange.length)
usedLength:NULL
encoding:NSUTF16LittleEndianStringEncoding
options:NSStringEncodingConversionAllowLossy
range:characterRange
remainingRange:NULL];
data->nickname_len = (u8)characterRange.length;
pthread_mutex_unlock(&mutex);
}
- (NSString *) nickname
{
pthread_mutex_lock(&mutex);
NSString *theNickname = [[[NSString alloc] initWithBytes:&data->nickname[0] length:(sizeof(UInt16) * data->nickname_len) encoding:NSUTF16LittleEndianStringEncoding] autorelease];
pthread_mutex_unlock(&mutex);
return theNickname;
}
- (void) setMessage:(NSString *)theMessage
{
if (theMessage == nil)
{
return;
}
pthread_mutex_lock(&mutex);
NSRange characterRange = {0, [theMessage length]};
if (characterRange.length > MAX_FW_MESSAGE_LENGTH)
{
characterRange.length = MAX_FW_MESSAGE_LENGTH;
}
[theMessage getBytes:&data->message[0]
maxLength:(sizeof(UInt16) * characterRange.length)
usedLength:NULL
encoding:NSUTF16LittleEndianStringEncoding
options:NSStringEncodingConversionAllowLossy
range:characterRange
remainingRange:NULL];
data->message_len = (u8)characterRange.length;
pthread_mutex_unlock(&mutex);
}
- (NSString *) message
{
pthread_mutex_lock(&mutex);
NSString *theMessage = [[[NSString alloc] initWithBytes:&data->message[0] length:(sizeof(UInt16) * data->message_len) encoding:NSUTF16LittleEndianStringEncoding] autorelease];
pthread_mutex_unlock(&mutex);
return theMessage;
}
- (void) setFavoriteColor:(NSInteger)colorID
{
pthread_mutex_lock(&mutex);
data->fav_colour = (u8)colorID;
pthread_mutex_unlock(&mutex);
}
- (NSInteger) favoriteColor
{
pthread_mutex_lock(&mutex);
NSInteger theFavoriteColorID = data->fav_colour;
pthread_mutex_unlock(&mutex);
return theFavoriteColorID;
}
- (void) setBirthday:(NSDate *)theDate
{
if (theDate == nil)
{
return;
}
pthread_mutex_lock(&mutex);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"M"];
NSInteger theMonth = [[dateFormatter stringFromDate:theDate] integerValue];
[dateFormatter setDateFormat:@"d"];
NSInteger theDay = [[dateFormatter stringFromDate:theDate] integerValue];
[dateFormatter setDateFormat:@"Y"];
NSInteger theYear = [[dateFormatter stringFromDate:theDate] integerValue];
[dateFormatter release];
data->birth_month = (u8)theMonth;
data->birth_day = (u8)theDay;
birth_year = theYear;
pthread_mutex_unlock(&mutex);
}
- (NSDate *) birthday
{
pthread_mutex_lock(&mutex);
NSDate *theBirthday = [NSDate dateWithString:[NSString stringWithFormat:@"%d-%d-%d 12:00:00 +0000", birth_year, data->birth_month, data->birth_day]];
pthread_mutex_unlock(&mutex);
return theBirthday;
}
- (void) setLanguage:(NSInteger)languageID
{
pthread_mutex_lock(&mutex);
data->language = (u8)languageID;
pthread_mutex_unlock(&mutex);
}
- (NSInteger) language
{
pthread_mutex_lock(&mutex);
NSInteger theLanguageID = data->language;
pthread_mutex_unlock(&mutex);
return theLanguageID;
}
- (void) update
{
// Write the attributes to the DS via the data struct.
// We have make a copy of the struct and send that so that the firmware
// changes get saved in CommonSettings.InternalFirmwareConf.
pthread_mutex_lock(&mutex);
struct NDS_fw_config_data newFirmwareData = *data;
NDS_CreateDummyFirmware(&newFirmwareData);
pthread_mutex_unlock(&mutex);
}
- (void) setDataWithDictionary:(NSDictionary *)dataDict
{
if (dataDict == nil)
{
return;
}
[self setConsoleType:[(NSNumber *)[dataDict valueForKey:@"ConsoleType"] integerValue]];
[self setNickname:(NSString *)[dataDict valueForKey:@"Nickname"]];
[self setMessage:(NSString *)[dataDict valueForKey:@"Message"]];
[self setFavoriteColor:[(NSNumber *)[dataDict valueForKey:@"FavoriteColor"] integerValue]];
[self setBirthday:(NSDate *)[dataDict valueForKey:@"Birthday"]];
[self setLanguage:[(NSNumber *)[dataDict valueForKey:@"Language"] integerValue]];
}
- (NSDictionary *) dataDictionary
{
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger:[self consoleType]], @"ConsoleType",
[self nickname], @"Nickname",
[self message], @"Message",
[NSNumber numberWithInteger:[self favoriteColor]], @"FavoriteColor",
[self birthday], @"Birthday",
[NSNumber numberWithInteger:[self language]], @"Language",
nil];
}
@end

View File

@ -0,0 +1,69 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include <IOKit/hid/IOHIDManager.h>
@interface CocoaHIDDevice : NSObject
{
IOHIDDeviceRef hidDeviceRef;
IOHIDQueueRef hidQueueRef;
NSRunLoop *runLoop;
}
@property (readonly) IOHIDDeviceRef hidDeviceRef;
@property (assign) 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;
}
@property (readonly) IOHIDManagerRef hidManagerRef;
@property (readonly) NSMutableSet *deviceList;
@property (assign) 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);

View File

@ -0,0 +1,840 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#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_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
#include <CoreServices/CoreServices.h>
#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_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
@implementation CocoaHIDDevice
@synthesize hidDeviceRef;
@synthesize 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);
[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
{
if (theRunLoop == nil && runLoop != nil)
{
IOHIDQueueRegisterValueAvailableCallback(hidQueueRef, NULL, NULL);
IOHIDQueueUnscheduleFromRunLoop(hidQueueRef, [runLoop getCFRunLoop], kCFRunLoopDefaultMode);
[runLoop release];
}
runLoop = theRunLoop;
if (runLoop != nil)
{
[runLoop retain];
IOHIDQueueScheduleWithRunLoop(hidQueueRef, [theRunLoop getCFRunLoop], kCFRunLoopDefaultMode);
IOHIDQueueRegisterValueAvailableCallback(hidQueueRef, HandleQueueValueAvailableCallback, self);
}
}
- (NSRunLoop *) runLoop
{
return runLoop;
}
- (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%04X/0x%04X", elementUsagePage, 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 %i", elementUsage];
}
else if (elementUsagePage == kHIDPage_VendorDefinedStart)
{
elementName = [NSString stringWithFormat:@"VendorDefined %i", elementUsage];
}
else
{
NSDictionary *elementUsagePageDict = (NSDictionary *)[hidUsageTable valueForKey:[NSString stringWithFormat:@"0x%04X", elementUsagePage]];
elementName = (NSString *)[elementUsagePageDict valueForKey:[NSString stringWithFormat:@"0x%04X", 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);
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) / 4) + logicalMin;
NSInteger upperThreshold = (((logicalMax - logicalMin) * 3) / 4) + logicalMin;
NSNumber *onState = [NSNumber numberWithBool:YES];
NSNumber *offState = [NSNumber numberWithBool:NO];
NSString *elementCodeLowerThreshold = [NSString stringWithFormat:@"0x%04X/0x%04X/LowerThreshold", elementUsagePage, elementUsage];
NSString *elementCodeUpperThreshold = [NSString stringWithFormat:@"0x%04X/0x%04X/UpperThreshold", elementUsagePage, 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%04X/0x%04X/%d-FourDirection", elementUsagePage, elementUsage, 0];
NSString *elementCodeFourWayRight = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-FourDirection", elementUsagePage, elementUsage, 1];
NSString *elementCodeFourWayDown = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-FourDirection", elementUsagePage, elementUsage, 2];
NSString *elementCodeFourWayLeft = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-FourDirection", elementUsagePage, elementUsage, 3];
NSString *elementCodeEightWayUp = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-EightDirection", elementUsagePage, elementUsage, 0];
NSString *elementCodeEightWayUpRight = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-EightDirection", elementUsagePage, elementUsage, 1];
NSString *elementCodeEightWayRight = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-EightDirection", elementUsagePage, elementUsage, 2];
NSString *elementCodeEightWayDownRight = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-EightDirection", elementUsagePage, elementUsage, 3];
NSString *elementCodeEightWayDown = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-EightDirection", elementUsagePage, elementUsage, 4];
NSString *elementCodeEightWayDownLeft = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-EightDirection", elementUsagePage, elementUsage, 5];
NSString *elementCodeEightWayLeft = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-EightDirection", elementUsagePage, elementUsage, 6];
NSString *elementCodeEightWayUpLeft = [NSString stringWithFormat:@"0x%04X/0x%04X/%d-EightDirection", elementUsagePage, 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;
@synthesize 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 arrayWithObjects:(NSMutableDictionary *)cfJoystickMatcher, (NSMutableDictionary *)cfGamepadMatcher, nil];
IOHIDManagerSetDeviceMatchingMultiple(hidManagerRef, (CFArrayRef)matcherArray);
[self setRunLoop:[NSRunLoop currentRunLoop]];
IOReturn result = IOHIDManagerOpen(hidManagerRef, kIOHIDOptionsTypeNone);
if (result != kIOReturnSuccess)
{
[self release];
return nil;
}
return self;
}
- (void)dealloc
{
[self.deviceList release];
self.runLoop = nil;
if (hidManagerRef != NULL)
{
IOHIDManagerClose(hidManagerRef, 0);
CFRelease(hidManagerRef);
hidManagerRef = NULL;
}
[super dealloc];
}
- (void) setRunLoop:(NSRunLoop *)theRunLoop
{
if (theRunLoop == nil && runLoop != nil)
{
IOHIDManagerRegisterDeviceMatchingCallback(hidManagerRef, NULL, NULL);
IOHIDManagerRegisterDeviceRemovalCallback(hidManagerRef, NULL, NULL);
IOHIDManagerUnscheduleFromRunLoop(hidManagerRef, [runLoop getCFRunLoop], kCFRunLoopDefaultMode);
[runLoop release];
}
runLoop = theRunLoop;
if (runLoop != nil)
{
[runLoop retain];
IOHIDManagerScheduleWithRunLoop(hidManagerRef, [theRunLoop getCFRunLoop], kCFRunLoopDefaultMode);
IOHIDManagerRegisterDeviceMatchingCallback(hidManagerRef, HandleDeviceMatchingCallback, self);
IOHIDManagerRegisterDeviceRemovalCallback(hidManagerRef, HandleDeviceRemovalCallback, self);
}
}
- (NSRunLoop *) runLoop
{
return runLoop;
}
@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;
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];
}
// 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:@"com.DeSmuME.DeSmuME.hidInputDetected" object:inputAttributesList userInfo:nil];
CFRelease(hidValueRef);
} while (1);
}

View File

@ -0,0 +1,89 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include <pthread.h>
@class CocoaDSMic;
@interface CocoaDSInput : NSObject
{
NSMutableDictionary *map;
NSString *deviceCode;
NSString *deviceName;
}
@property (assign) NSMutableDictionary *map;
@property (assign) NSString *deviceCode;
@property (assign) 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
@interface CocoaDSController : NSObject
{
NSMutableDictionary *states;
CocoaDSMic *cdsMic;
pthread_mutex_t *mutexControllerUpdate;
NSMutableDictionary *inputs;
}
@property (assign) NSMutableDictionary *states;
@property (assign) CocoaDSMic *cdsMic;
@property (assign) NSMutableDictionary *inputs;
@property (readonly) pthread_mutex_t *mutexControllerUpdate;
- (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;
@end

View File

@ -0,0 +1,648 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "cocoa_input.h"
#import "cocoa_globals.h"
#import "cocoa_mic.h"
#include "../NDSSystem.h"
#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] init];
deviceCode = theCode;
deviceName = theName;
if (theCode == nil)
{
deviceCode = [NSString stringWithFormat:@"0x%08X", rand()];
}
if (theName == nil)
{
deviceName = @"Unknown Device ";
deviceName = [deviceName stringByAppendingString:deviceCode];
}
return self;
}
- (void)dealloc
{
[self.map release];
[super dealloc];
}
- (void) set:(NSString *)elementCode attributes:(NSDictionary *)mappingAttributes
{
NSString *keyString = [[self.deviceCode stringByAppendingString:@":"] stringByAppendingString:elementCode];
[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
{
self = [super init];
if (self == nil)
{
return self;
}
mutexControllerUpdate = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutexControllerUpdate, NULL);
states = [[NSMutableDictionary alloc] init];
cdsMic = [[CocoaDSMic alloc] init];
inputs = [[NSMutableDictionary alloc] initWithCapacity:10];
[self initDefaultMappings];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleHIDInput:)
name:@"com.DeSmuME.DeSmuME.hidInputDetected"
object:nil];
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self.states release];
[self.cdsMic release];
[self.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];
[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:@"%i", [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
{
self.cdsMic.mode = inputMode;
}
- (void) update
{
pthread_mutex_lock(self.mutexControllerUpdate);
// 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"]);
// Setup the DS touch pad.
if ([self isInputPressed:@"Touch"])
{
NSPoint touchLocation = [self inputLocation:@"Touch"];
NDS_setTouchPos((u16)touchLocation.x, (u16)touchLocation.y);
}
else
{
NDS_releaseTouch();
}
// 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)
{
[self.cdsMic fillWithNullSamples];
}
else if (self.cdsMic.mode == MICMODE_INTERNAL_NOISE)
{
[self.cdsMic fillWithInternalNoise];
}
else if (self.cdsMic.mode == MICMODE_WHITE_NOISE)
{
[self.cdsMic fillWithWhiteNoise];
}
else if (self.cdsMic.mode == MICMODE_SOUND_FILE)
{
// TODO: Need to implement. Does nothing for now.
}
}
}
- (void) handleHIDInput:(NSNotification *)aNotification
{
NSArray *inputPropertiesList = (NSArray *)[aNotification object];
[self setStateWithMultipleInputs:inputPropertiesList];
}
@end

View File

@ -0,0 +1,63 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#define NUM_INTERNAL_NOISE_SAMPLES 32
static const UInt8 noiseSample[NUM_INTERNAL_NOISE_SAMPLES] =
{
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0xFF,
0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01
};
@interface CocoaDSMic : NSObject
{
UInt8 *buffer;
UInt8 *readPosition;
UInt8 *writePosition;
NSUInteger fillCount;
BOOL needsActivate;
NSInteger mode;
NSUInteger internalSamplePosition;
}
@property (readonly) UInt8 *buffer;
@property (readonly) UInt8 *readPosition;
@property (readonly) UInt8 *writePosition;
@property (readonly) NSUInteger fillCount;
@property (assign) BOOL needsActivate;
@property (assign) NSInteger mode;
- (void) clear;
- (NSUInteger) fillCountRemaining;
- (BOOL) isFull;
- (BOOL) isEmpty;
- (UInt8) read;
- (void) write:(UInt8)theSample;
- (UInt8) generateInternalNoiseSample;
- (UInt8) generateWhiteNoiseSample;
- (void) fillWithNullSamples;
- (void) fillWithInternalNoise;
- (void) fillWithWhiteNoise;
+ (CocoaDSMic *) masterMic;
+ (void) setMasterMic:(CocoaDSMic *)theMic;
@end

View File

@ -0,0 +1,251 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "cocoa_mic.h"
#import "cocoa_globals.h"
#include "../NDSSystem.h"
#undef BOOL
static CocoaDSMic *masterMic = nil;
@implementation CocoaDSMic
@synthesize buffer;
@synthesize readPosition;
@synthesize writePosition;
@synthesize fillCount;
@synthesize needsActivate;
@synthesize mode;
- (id)init
{
self = [super init];
if (self == nil)
{
return self;
}
UInt8 *newBuffer = (UInt8 *)malloc(MIC_BUFFER_SIZE);
if (newBuffer == nil)
{
[self release];
return nil;
}
buffer = newBuffer;
[self clear];
internalSamplePosition = 0;
needsActivate = YES;
mode = MICMODE_NONE;
[CocoaDSMic setMasterMic:self];
return self;
}
- (void)dealloc
{
if ([CocoaDSMic masterMic] == self)
{
[CocoaDSMic setMasterMic:nil];
}
free(buffer);
buffer = NULL;
[super dealloc];
}
- (void) mode:(NSInteger)theMode
{
switch (theMode)
{
case MICMODE_NONE:
self.needsActivate = YES;
break;
case MICMODE_INTERNAL_NOISE:
self.needsActivate = YES;
break;
case MICMODE_SOUND_FILE:
self.needsActivate = YES;
break;
case MICMODE_WHITE_NOISE:
self.needsActivate = YES;
break;
case MICMODE_PHYSICAL:
self.needsActivate = NO;
break;
default:
break;
}
}
- (void) clear
{
memset(buffer, MIC_NULL_SAMPLE_VALUE, MIC_BUFFER_SIZE);
readPosition = buffer;
writePosition = buffer;
fillCount = 0;
}
- (NSUInteger) fillCountRemaining
{
return (MIC_MAX_BUFFER_SAMPLES - self.fillCount);
}
- (BOOL) isFull
{
return (self.fillCount >= MIC_MAX_BUFFER_SAMPLES);
}
- (BOOL) isEmpty
{
return (self.fillCount == 0);
}
- (UInt8) read
{
UInt8 theSample = MIC_NULL_SAMPLE_VALUE;
bool isMicActive = NDS_getFinalUserInput().mic.micButtonPressed;
if ([self isEmpty] || (self.needsActivate && !isMicActive))
{
return theSample;
}
theSample = *readPosition;
readPosition++;
fillCount--;
// Move the pointer back to start if we reach the end of the memory block.
if (readPosition >= (buffer + MIC_BUFFER_SIZE))
{
readPosition = buffer;
}
return theSample;
}
- (void) write:(UInt8)theSample
{
if ([self isFull])
{
return;
}
*writePosition = theSample;
writePosition++;
fillCount++;
// Move the pointer back to start if we reach the end of the memory block.
if (writePosition >= (buffer + MIC_BUFFER_SIZE))
{
writePosition = buffer;
}
}
- (UInt8) generateInternalNoiseSample
{
internalSamplePosition++;
if (internalSamplePosition >= NUM_INTERNAL_NOISE_SAMPLES)
{
internalSamplePosition = 0;
}
return noiseSample[internalSamplePosition];
}
- (UInt8) generateWhiteNoiseSample
{
return (UInt8)(rand() & 0xFF);
}
- (void) fillWithNullSamples
{
while (self.fillCount < MIC_MAX_BUFFER_SAMPLES)
{
[self write:MIC_NULL_SAMPLE_VALUE];
}
}
- (void) fillWithInternalNoise
{
while (self.fillCount < MIC_MAX_BUFFER_SAMPLES)
{
[self write:[self generateInternalNoiseSample]];
}
}
- (void) fillWithWhiteNoise
{
while (self.fillCount < MIC_MAX_BUFFER_SAMPLES)
{
[self write:[self generateWhiteNoiseSample]];
}
}
+ (CocoaDSMic *) masterMic
{
return masterMic;
}
+ (void) setMasterMic:(CocoaDSMic *)theMic
{
masterMic = theMic;
}
@end
BOOL Mic_Init()
{
// Do nothing. The CocoaDSMic object will take care of this.
return TRUE;
}
void Mic_Reset()
{
// Do nothing.
}
void Mic_DeInit()
{
// Do nothing. The CocoaDSMic object will take care of this.
}
u8 Mic_ReadSample()
{
return [masterMic read];
}
void mic_savestate(EMUFILE* os)
{
write32le(-1, os);
}
bool mic_loadstate(EMUFILE* is, int size)
{
is->fseek(size, SEEK_CUR);
return true;
}

View File

@ -0,0 +1,207 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include <pthread.h>
#include <libkern/OSAtomic.h>
#import "cocoa_util.h"
@interface CocoaDSOutput : CocoaDSThread
{
BOOL isStateChanged;
NSUInteger frameCount;
NSData *frameData;
NSMutableDictionary *property;
pthread_mutex_t *mutexOutputFrame;
}
@property (assign) BOOL isStateChanged;
@property (assign) NSUInteger frameCount;
@property (assign) NSData *frameData;
@property (assign) NSMutableDictionary *property;
@property (readonly) pthread_mutex_t *mutexOutputFrame;
- (void) doCoreEmuFrame;
- (void) handleEmuFrameProcessed:(NSData *)theData;
@end
@interface CocoaDSSpeaker : CocoaDSOutput
{
NSUInteger bufferSize;
OSSpinLock spinlockAudioOutputEngine;
OSSpinLock spinlockVolume;
OSSpinLock spinlockSpuAdvancedLogic;
OSSpinLock spinlockSpuInterpolationMode;
OSSpinLock spinlockSpuSyncMode;
OSSpinLock spinlockSpuSyncMethod;
}
@property (assign) NSUInteger bufferSize;
- (id) init;
- (id) initWithVolume:(CGFloat)vol;
- (void) dealloc;
+ (BOOL) startupSPU;
+ (void) shutdownSPU;
+ (BOOL) isSPUStarted;
- (void) setVolume:(float)vol;
- (float) volume;
- (void) setAudioOutputEngine:(NSInteger)methodID;
- (NSInteger) audioOutputEngine;
- (void) setSpuAdvancedLogic:(BOOL)state;
- (BOOL) spuAdvancedLogic;
- (void) setSpuInterpolationMode:(NSInteger)modeID;
- (NSInteger) spuInterpolationMode;
- (void) setSpuSyncMode:(NSInteger)modeID;
- (NSInteger) spuSyncMode;
- (void) setSpuSyncMethod:(NSInteger)methodID;
- (NSInteger) spuSyncMethod;
- (BOOL) mute;
- (void) setMute:(BOOL)mute;
- (NSInteger) filter;
- (void) setFilter:(NSInteger)filter;
- (void) handleSetVolume:(NSData *)volumeData;
- (void) handleSetAudioOutputEngine:(NSData *)methodIdData;
- (void) handleSetSpuAdvancedLogic:(NSData *)stateData;
- (void) handleSetSpuSyncMode:(NSData *)modeIdData;
- (void) handleSetSpuSyncMethod:(NSData *)methodIdData;
- (void) handleSetSpuInterpolationMode:(NSData *)modeIdData;
@end
@class CocoaVideoFilter;
@protocol CocoaDSDisplayDelegate <NSObject>
@required
- (void) doInitVideoOutput:(NSDictionary *)properties;
- (void) doProcessVideoFrame:(const void *)videoFrameData frameSize:(NSSize)frameSize;
@property (assign) NSPort *sendPortDisplay;
@optional
- (void) doResizeView:(NSRect)rect;
- (void) doRedraw;
- (void) doDisplayTypeChanged:(NSInteger)displayTypeID;
- (void) doBilinearOutputChanged:(BOOL)useBilinear;
- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID;
@property (assign) BOOL isHudEnabled;
@property (assign) BOOL isHudEditingModeEnabled;
@end
@interface CocoaDSDisplay : CocoaDSOutput
{
UInt32 gpuStateFlags;
id <CocoaDSDisplayDelegate> delegate;
NSInteger displayType;
CocoaVideoFilter *vf;
pthread_mutex_t *mutexRender3D;
OSSpinLock spinlockGpuState;
OSSpinLock spinlockDisplayType;
OSSpinLock spinlockVideoFilterType;
OSSpinLock spinlockVfSrcBuffer;
OSSpinLock spinlockRender3DRenderingEngine;
OSSpinLock spinlockRender3DHighPrecisionColorInterpolation;
OSSpinLock spinlockRender3DEdgeMarking;
OSSpinLock spinlockRender3DFog;
OSSpinLock spinlockRender3DTextures;
OSSpinLock spinlockRender3DDepthComparisonThreshold;
OSSpinLock spinlockRender3DThreads;
OSSpinLock spinlockRender3DLineHack;
}
@property (assign) UInt32 gpuStateFlags;
@property (assign) id <CocoaDSDisplayDelegate> delegate;
@property (assign) NSInteger displayType;
@property (assign) CocoaVideoFilter *vf;
@property (readonly) pthread_mutex_t *mutexRender3D;
- (void) setRender3DRenderingEngine:(NSInteger)methodID;
- (NSInteger) render3DRenderingEngine;
- (void) setRender3DHighPrecisionColorInterpolation:(BOOL)state;
- (BOOL) render3DHighPrecisionColorInterpolation;
- (void) setRender3DEdgeMarking:(BOOL)state;
- (BOOL) render3DEdgeMarking;
- (void) setRender3DFog:(BOOL)state;
- (BOOL) render3DFog;
- (void) setRender3DTextures:(BOOL)state;
- (BOOL) render3DTextures;
- (void) setRender3DDepthComparisonThreshold:(NSUInteger)threshold;
- (NSUInteger) render3DDepthComparisonThreshold;
- (void) setRender3DThreads:(NSUInteger)numberThreads;
- (NSUInteger) render3DThreads;
- (void) setRender3DLineHack:(BOOL)state;
- (BOOL) render3DLineHack;
- (void) handleResizeView:(NSData *)rectData;
- (void) handleRedrawView;
- (void) handleChangeGpuStateFlags:(NSData *)flagsData;
- (void) handleChangeDisplayType:(NSData *)displayTypeIdData;
- (void) handleChangeBilinearOutput:(NSData *)bilinearStateData;
- (void) handleChangeVideoFilter:(NSData *)videoFilterTypeIdData;
- (void) handleSetRender3DRenderingEngine:(NSData *)methodIdData;
- (void) handleSetRender3DHighPrecisionColorInterpolation:(NSData *)stateData;
- (void) handleSetRender3DEdgeMarking:(NSData *)stateData;
- (void) handleSetRender3DFog:(NSData *)stateData;
- (void) handleSetRender3DTextures:(NSData *)stateData;
- (void) handleSetRender3DDepthComparisonThreshold:(NSData *)thresholdData;
- (void) handleSetRender3DThreads:(NSData *)numberThreadsData;
- (void) handleSetRender3DLineHack:(NSData *)stateData;
- (void) handleSetViewToBlack;
- (void) handleSetViewToWhite;
- (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData;
- (void) handleCopyToPasteboard;
- (NSImage *) image;
- (NSBitmapImageRep *) bitmapImageRep;
- (BOOL) gpuStateByBit:(UInt32)stateBit;
- (BOOL) isGPUTypeDisplayed:(NSInteger)theGpuType;
- (void) hideGPUType:(NSInteger)theGpuType;
- (void) showGPUType:(NSInteger)theGpuType;
@end
#ifdef __cplusplus
extern "C"
{
#endif
bool opengl_init();
void HandleMessageEchoResponse(NSPortMessage *portMessage);
void SetGPULayerState(int displayType, unsigned int i, bool state);
bool GetGPULayerState(int displayType, unsigned int i);
void SetGPUDisplayState(int displayType, bool state);
bool GetGPUDisplayState(int displayType);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include <libkern/OSAtomic.h>
@interface CocoaDSRom : NSObject
{
NSMutableDictionary *header;
NSMutableDictionary *bindings;
NSURL *fileURL;
BOOL isDataLoaded;
NSInteger saveType;
NSMutableDictionary *xmlCurrentRom;
NSMutableArray *xmlElementStack;
NSMutableArray *xmlCharacterStack;
}
@property (assign) NSMutableDictionary *header;
@property (assign) NSMutableDictionary *bindings;
@property (assign) NSURL *fileURL;
@property (assign) BOOL isDataLoaded;
@property (assign) NSInteger saveType;
- (id) initWithURL:(NSURL *)theURL;
- (id) initWithURL:(NSURL *)theURL saveType:(NSInteger)saveTypeID;
- (void) initHeader;
- (BOOL) loadData:(NSURL *)theURL;
- (void) loadDataOnThread:(id)object;
- (NSString *) getRomTitle;
- (NSString *) getRomCode;
- (NSString *) getRomBannerTitle:(const UInt16 *)title;
- (NSString *) getRomInternalName;
- (NSString *) getRomSerial;
- (NSImage *) icon;
- (void) handleAdvansceneDatabaseInfo;
+ (void) changeRomSaveType:(NSInteger)saveTypeID;
+ (NSInteger) saveTypeByString:(NSString *)saveTypeString;
+ (NSMutableDictionary *) romNotLoadedBindings;
@end
#ifdef __cplusplus
extern "C"
{
#endif
void RomIconToRGBA8888(uint32_t *bitmapData);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,649 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "cocoa_rom.h"
#import "cocoa_file.h"
#import "cocoa_globals.h"
#import "cocoa_util.h"
#include "../NDSSystem.h"
#include "../mc.h"
#undef BOOL
@implementation CocoaDSRom
@synthesize header;
@synthesize bindings;
@synthesize fileURL;
@synthesize isDataLoaded;
@synthesize saveType;
static NSMutableDictionary *saveTypeValues = nil;
- (id)init
{
return [self initWithURL:nil];
}
- (id) initWithURL:(NSURL *)theURL
{
return [self initWithURL:theURL saveType:ROMSAVETYPE_AUTOMATIC];
}
- (id) initWithURL:(NSURL *)theURL saveType:(NSInteger)saveTypeID
{
self = [super init];
if (self == nil)
{
return self;
}
if (saveTypeValues == nil)
{
saveTypeValues = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInteger:1], @"eeprom - 4 kbit",
[NSNumber numberWithInteger:2], @"eeprom - 64 kbit",
[NSNumber numberWithInteger:3], @"eeprom - 512 kbit",
[NSNumber numberWithInteger:5], @"flash - 2 mbit",
[NSNumber numberWithInteger:6], @"flash - 4 mbit",
[NSNumber numberWithInteger:7], @"flash - 8 mbit",
[NSNumber numberWithInteger:10], @"flash - 64 mbit",
[NSNumber numberWithInteger:0], @"none",
[NSNumber numberWithInteger:0], @"tbc",
nil];
}
header = [[NSMutableDictionary alloc] init];
if (header == nil)
{
[self release];
self = nil;
return self;
}
bindings = [[CocoaDSRom romNotLoadedBindings] retain];
if (bindings == nil)
{
[header release];
[self release];
self = nil;
return self;
}
fileURL = nil;
isDataLoaded = NO;
saveType = saveTypeID;
xmlCurrentRom = nil;
xmlElementStack = [[NSMutableArray alloc] initWithCapacity:32];
xmlCharacterStack = [[NSMutableArray alloc] initWithCapacity:32];
if (theURL != nil)
{
[self loadData:theURL];
}
return self;
}
- (void)dealloc
{
if (self.isDataLoaded)
{
NDS_FreeROM();
self.isDataLoaded = NO;
}
[xmlElementStack release];
[xmlCharacterStack release];
[self.header release];
self.header = nil;
[self.bindings release];
self.bindings = nil;
[self.fileURL release];
self.fileURL = nil;
[super dealloc];
}
- (void) initHeader
{
const NDS_header *ndsRomHeader = NDS_getROMHeader();
const RomBanner &ndsRomBanner = gameInfo.getRomBanner();
if(self.header == nil || self.bindings == nil)
{
return;
}
if (&ndsRomBanner != NULL)
{
[self.header setValue:[self getRomBannerTitle:ndsRomBanner.titles[0]] forKey:@"bannerJapanese"];
[self.header setValue:[self getRomBannerTitle:ndsRomBanner.titles[1]] forKey:@"bannerEnglish"];
[self.header setValue:[self getRomBannerTitle:ndsRomBanner.titles[2]] forKey:@"bannerFrench"];
[self.header setValue:[self getRomBannerTitle:ndsRomBanner.titles[3]] forKey:@"bannerGerman"];
[self.header setValue:[self getRomBannerTitle:ndsRomBanner.titles[4]] forKey:@"bannerItalian"];
[self.header setValue:[self getRomBannerTitle:ndsRomBanner.titles[5]] forKey:@"bannerSpanish"];
[self.bindings setValue:[self.header objectForKey:@"bannerJapanese"] forKey:@"bannerJapanese"];
[self.bindings setValue:[self.header objectForKey:@"bannerEnglish"] forKey:@"bannerEnglish"];
[self.bindings setValue:[self.header objectForKey:@"bannerFrench"] forKey:@"bannerFrench"];
[self.bindings setValue:[self.header objectForKey:@"bannerGerman"] forKey:@"bannerGerman"];
[self.bindings setValue:[self.header objectForKey:@"bannerItalian"] forKey:@"bannerItalian"];
[self.bindings setValue:[self.header objectForKey:@"bannerSpanish"] forKey:@"bannerSpanish"];
}
if (ndsRomHeader != NULL)
{
[self.header setValue:[self getRomTitle] forKey:@"gameTitle"];
[self.header setValue:[self getRomCode] forKey:@"gameCode"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->makerCode] forKey:@"makerCode"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->cardSize] forKey:@"romSize"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ARM9src] forKey:@"arm9BinaryOffset"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ARM9exe] forKey:@"arm9BinaryEntryAddress"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ARM9cpy] forKey:@"arm9BinaryStartAddress"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ARM9binSize] forKey:@"arm9BinarySize"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ARM7src] forKey:@"arm7BinaryOffset"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ARM7exe] forKey:@"arm7BinaryEntryAddress"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ARM7cpy] forKey:@"arm7BinaryStartAddress"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ARM7binSize] forKey:@"arm7BinarySize"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->FNameTblOff] forKey:@"fntOffset"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->FNameTblSize] forKey:@"fntTableSize"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->FATOff] forKey:@"fatOffset"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->FATSize] forKey:@"fatSize"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->IconOff] forKey:@"iconOffset"];
[self.header setValue:[NSNumber numberWithInteger:ndsRomHeader->ROMSize] forKey:@"usedRomSize"];
[self.bindings setValue:[self.header objectForKey:@"gameTitle"] forKey:@"gameTitle"];
[self.bindings setValue:[self.header objectForKey:@"gameCode"] forKey:@"gameCode"];
[self.bindings setValue:[NSString stringWithFormat:@"%04Xh", [[self.header objectForKey:@"makerCode"] intValue]] forKey:@"makerCode"];
[self.bindings setValue:[NSString stringWithFormat:@"%i", [[self.header objectForKey:@"romSize"] intValue]] forKey:@"romSize"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"arm9BinaryOffset"] intValue]] forKey:@"arm9BinaryOffset"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"arm9BinaryEntryAddress"] intValue]] forKey:@"arm9BinaryEntryAddress"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"arm9BinaryStartAddress"] intValue]] forKey:@"arm9BinaryStartAddress"];
[self.bindings setValue:[NSString stringWithFormat:NSSTRING_STATUS_SIZE_BYTES, [[self.header objectForKey:@"arm9BinarySize"] intValue]] forKey:@"arm9BinarySize"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"arm7BinaryOffset"] intValue]] forKey:@"arm7BinaryOffset"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"arm7BinaryEntryAddress"] intValue]] forKey:@"arm7BinaryEntryAddress"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"arm7BinaryStartAddress"] intValue]] forKey:@"arm7BinaryStartAddress"];
[self.bindings setValue:[NSString stringWithFormat:NSSTRING_STATUS_SIZE_BYTES, [[self.header objectForKey:@"arm7BinarySize"] intValue]] forKey:@"arm7BinarySize"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"fntOffset"] intValue]] forKey:@"fntOffset"];
[self.bindings setValue:[NSString stringWithFormat:NSSTRING_STATUS_SIZE_BYTES, [[self.header objectForKey:@"fntTableSize"] intValue]] forKey:@"fntTableSize"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"fatOffset"] intValue]] forKey:@"fatOffset"];
[self.bindings setValue:[NSString stringWithFormat:NSSTRING_STATUS_SIZE_BYTES, [[self.header objectForKey:@"fatSize"] intValue]] forKey:@"fatSize"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"fatOffset"] intValue]] forKey:@"fatOffset"];
[self.bindings setValue:[NSString stringWithFormat:@"0x%08X", [[self.header objectForKey:@"iconOffset"] intValue]] forKey:@"iconOffset"];
[self.bindings setValue:[NSString stringWithFormat:@"%i", [[self.header objectForKey:@"usedRomSize"] intValue]] forKey:@"usedRomSize"];
}
// Get ROM image
NSImage *iconImage = [self icon];
if (iconImage != nil)
{
[header setObject:iconImage forKey:@"iconImage"];
[self.bindings setObject:(NSImage *)[self.header objectForKey:@"iconImage"] forKey:@"iconImage"];
}
[self.header setValue:[self getRomInternalName] forKey:@"romInternalName"];
[self.header setValue:[self getRomSerial] forKey:@"romSerial"];
[self.bindings setValue:[self.header objectForKey:@"romInternalName"] forKey:@"romInternalName"];
[self.bindings setValue:[self.header objectForKey:@"romSerial"] forKey:@"romSerial"];
}
- (BOOL) loadData:(NSURL *)theURL
{
[CocoaDSRom changeRomSaveType:saveType];
BOOL result = [CocoaDSFile loadRom:theURL];
if (!result)
{
NSMutableDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], @"DidLoad", nil];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"com.DeSmuME.DeSmuME.loadRomDidFinish" object:self userInfo:userInfo];
return result;
}
self.fileURL = [theURL copyWithZone:nil];
self.isDataLoaded = YES;
[self initHeader];
NSString *advscDBPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"Advanscene_DatabasePath"];
if (advscDBPath != nil)
{
NSError *xmlError = [[NSError alloc] init];
NSXMLParser *advscDB = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL fileURLWithPath:advscDBPath]];
[advscDB setDelegate:self];
[advscDB parse];
[advscDB release];
[xmlError release];
}
NSMutableDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"DidLoad", self.fileURL, @"URL", nil];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"com.DeSmuME.DeSmuME.loadRomDidFinish" object:self userInfo:userInfo];
return result;
}
- (void) loadDataOnThread:(id)object
{
NSURL *theURL = [(NSURL *)object copyWithZone:nil];
NSAutoreleasePool *threadPool = [[NSAutoreleasePool alloc] init];
[self loadData:theURL];
[threadPool release];
[theURL release];
}
- (NSString *) getRomTitle
{
NDS_header *ndsRomHeader = NDS_getROMHeader();
if (ndsRomHeader == nil)
{
return nil;
}
return [[[NSString alloc] initWithBytes:ndsRomHeader->gameTile length:ROMINFO_GAME_TITLE_LENGTH encoding:NSUTF8StringEncoding] autorelease];
}
- (NSString *) getRomCode
{
NDS_header *ndsRomHeader = NDS_getROMHeader();
if (ndsRomHeader == nil)
{
return nil;
}
return [[[NSString alloc] initWithBytes:ndsRomHeader->gameCode length:ROMINFO_GAME_CODE_LENGTH encoding:NSUTF8StringEncoding] autorelease];
}
- (NSString *) getRomBannerTitle:(const UInt16 *)title
{
NSUInteger titleLength = ROMINFO_GAME_BANNER_LENGTH * sizeof(*title);
return [[[NSString alloc] initWithBytes:title length:titleLength encoding:NSUTF16LittleEndianStringEncoding] autorelease];
}
- (NSString *) getRomInternalName
{
return [NSString stringWithCString:gameInfo.ROMname encoding:NSUTF8StringEncoding];
}
- (NSString *) getRomSerial
{
return [NSString stringWithCString:gameInfo.ROMserial encoding:NSUTF8StringEncoding];
}
- (NSImage *) icon
{
NSImage *newImage = nil;
NDS_header *ndsRomHeader = NDS_getROMHeader();
if (ndsRomHeader == nil)
{
return newImage;
}
NSUInteger iconOffset = ndsRomHeader->IconOff;
if(iconOffset == 0)
{
return newImage;
}
newImage = [[NSImage alloc] initWithSize:NSMakeSize(32, 32)];
if(newImage == nil)
{
return newImage;
}
NSUInteger w = ROM_ICON_WIDTH;
NSUInteger h = ROM_ICON_HEIGHT;
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:w
pixelsHigh:h
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bytesPerRow:w * 4
bitsPerPixel:32];
if(imageRep == nil)
{
[newImage release];
newImage = nil;
return newImage;
}
uint32_t *bitmapData = (uint32_t *)[imageRep bitmapData];
RomIconToRGBA8888(bitmapData);
#ifdef __BIG_ENDIAN__
uint32_t *bitmapDataEnd = bitmapData + (w * h);
while (bitmapData < bitmapDataEnd)
{
*bitmapData++ = CFSwapInt32LittleToHost(*bitmapData);
}
#endif
[imageRep autorelease];
[newImage addRepresentation:imageRep];
return [newImage autorelease];
}
- (void) handleAdvansceneDatabaseInfo
{
if (xmlCurrentRom == nil)
{
return;
}
// Set the ROM save type.
BOOL useAdvscForRomSave = [[NSUserDefaults standardUserDefaults] boolForKey:@"Advanscene_AutoDetectRomSaveType"];
if (useAdvscForRomSave && (saveType == ROMSAVETYPE_AUTOMATIC))
{
NSString *saveTypeString = (NSString *)[xmlCurrentRom valueForKey:@"saveType"];
NSInteger saveTypeID = [CocoaDSRom saveTypeByString:saveTypeString];
[CocoaDSRom changeRomSaveType:saveTypeID];
if (saveTypeID != ROMSAVETYPE_AUTOMATIC)
{
NSLog(@"Set the ROM save type using the ADVANsCEne database: %s.", [saveTypeString cStringUsingEncoding:NSUTF8StringEncoding]);
}
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
NSMutableString *xmlCharacters = [NSMutableString stringWithCapacity:1024];
[xmlCharacters setString:@""];
[xmlCharacterStack addObject:xmlCharacters];
[xmlElementStack addObject:elementName];
if ([elementName isEqualToString:@"game"])
{
if (xmlCurrentRom == nil)
{
xmlCurrentRom = [[NSMutableDictionary alloc] initWithCapacity:32];
}
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
{
NSString *xmlElement = (NSString *)[xmlElementStack lastObject];
if (xmlElement == nil || ![xmlElement isEqualToString:elementName])
{
return;
}
NSMutableString *xmlCharacters = (NSMutableString *)[xmlCharacterStack lastObject];
[xmlCharacters setString:[xmlCharacters stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
if ([elementName isEqualToString:@"game"])
{
NSString *romHeaderSerial = (NSString *)[self.header valueForKey:@"romSerial"];
NSString *xmlSerial = (NSString *)[xmlCurrentRom valueForKey:@"serial"];
if ([xmlSerial isEqualToString:romHeaderSerial])
{
[self handleAdvansceneDatabaseInfo];
[parser abortParsing];
}
[xmlCurrentRom release];
xmlCurrentRom = nil;
}
else
{
if (xmlCurrentRom != nil)
{
[xmlCurrentRom setValue:[NSString stringWithString:xmlCharacters] forKey:elementName];
}
}
[xmlCharacterStack removeLastObject];
[xmlElementStack removeLastObject];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSMutableString *xmlCharacters = (NSMutableString *)[xmlCharacterStack lastObject];
if (xmlCharacters != nil)
{
[xmlCharacters appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSInteger errorCode = [parseError code];
if (errorCode == NSXMLParserDelegateAbortedParseError)
{
return;
}
}
+ (void) changeRomSaveType:(NSInteger)saveTypeID
{
CommonSettings.manualBackupType = (int)saveTypeID;
if (saveTypeID != ROMSAVETYPE_AUTOMATIC)
{
backup_forceManualBackupType();
}
}
+ (NSInteger) saveTypeByString:(NSString *)saveTypeString
{
NSInteger saveTypeID = 0;
if (saveTypeValues == nil)
{
return saveTypeID;
}
NSNumber *saveTypeNumber = (NSNumber *)[saveTypeValues valueForKey:[saveTypeString lowercaseString]];
if (saveTypeNumber == nil)
{
return saveTypeID;
}
saveTypeID = [saveTypeNumber integerValue];
return saveTypeID;
}
+ (NSMutableDictionary *) romNotLoadedBindings
{
NSImage *iconImage = [[[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"AppIcon_DeSmuME" ofType:@"icns"]] autorelease];
return [NSMutableDictionary dictionaryWithObjectsAndKeys:
NSSTRING_STATUS_NO_ROM_LOADED, @"romInternalName",
NSSTRING_STATUS_NO_ROM_LOADED, @"romSerial",
NSSTRING_STATUS_NO_ROM_LOADED, @"bannerJapanese",
NSSTRING_STATUS_NO_ROM_LOADED, @"bannerEnglish",
NSSTRING_STATUS_NO_ROM_LOADED, @"bannerFrench",
NSSTRING_STATUS_NO_ROM_LOADED, @"bannerGerman",
NSSTRING_STATUS_NO_ROM_LOADED, @"bannerItalian",
NSSTRING_STATUS_NO_ROM_LOADED, @"bannerSpanish",
NSSTRING_STATUS_NO_ROM_LOADED, @"gameTitle",
NSSTRING_STATUS_NO_ROM_LOADED, @"gameCode",
NSSTRING_STATUS_NO_ROM_LOADED, @"makerCode",
[NSString stringWithFormat:NSSTRING_STATUS_NO_ROM_LOADED, 0], @"romSize",
[NSString stringWithFormat:@"0x%08X", 0], @"arm9BinaryOffset",
[NSString stringWithFormat:@"0x%08X", 0], @"arm9BinaryEntryAddress",
[NSString stringWithFormat:@"0x%08X", 0], @"arm9BinaryStartAddress",
[NSString stringWithFormat:NSSTRING_STATUS_SIZE_BYTES, 0], @"arm9BinarySize",
[NSString stringWithFormat:@"0x%08X", 0], @"arm7BinaryOffset",
[NSString stringWithFormat:@"0x%08X", 0], @"arm7BinaryEntryAddress",
[NSString stringWithFormat:@"0x%08X", 0], @"arm7BinaryStartAddress",
[NSString stringWithFormat:NSSTRING_STATUS_SIZE_BYTES, 0], @"arm7BinarySize",
[NSString stringWithFormat:@"0x%08X", 0], @"fntOffset",
[NSString stringWithFormat:NSSTRING_STATUS_SIZE_BYTES, 0], @"fntTableSize",
[NSString stringWithFormat:@"0x%08X", 0], @"fatOffset",
[NSString stringWithFormat:NSSTRING_STATUS_SIZE_BYTES, 0], @"fatSize",
[NSString stringWithFormat:@"0x%08X", 0], @"iconOffset",
[NSString stringWithFormat:NSSTRING_STATUS_NO_ROM_LOADED, 0], @"usedRomSize",
iconImage, @"iconImage",
nil];
}
@end
/********************************************************************************************
RomIconToRGBA8888()
Reads the icon image data from a ROM and converts it to an RGBA8888 formatted bitmap.
Takes:
bitmapData - Write pointer for the icon's pixel data.
Returns:
Nothing.
Details:
- If bitmapData is NULL, then this function immediately returns and does nothing.
- If no ROM is loaded, then bitmapData will have a black square icon.
- The caller is responsible for ensuring that bitmapData points to a valid
memory location and that the memory block is large enough to hold the pixel
data. The written data will be 32x32 pixels in 32-bit color. Therefore, a size
of at least 4096 bytes must be allocated.
********************************************************************************************/
void RomIconToRGBA8888(uint32_t *bitmapData)
{
const NDS_header *ndsRomHeader = NDS_getROMHeader(); // Contains the memory addresses we need to get our read pointer locations.
int iconOffset; // Memory location offset for the ROM icon data.
const uint16_t *iconClutPtr; // Read pointer for the icon's CLUT.
const uint32_t *iconPixPtr; // Read pointer for the icon's pixel data.
uint32_t clut[16]; // 4-bit indexed CLUT, storing RGBA8888 values for each color.
uint32_t pixRowColors; // Temp location for storing an 8 pixel row of 4-bit indexed color values from the icon's pixel data.
unsigned int pixRowIndex; // Temp location for tracking which pixel row of an 8x8 square that we are reading.
unsigned int x; // Temp location for tracking which of the 8x8 pixel squares that we are reading (x-dimension).
unsigned int y; // Temp location for tracking which of the 8x8 pixel squares that we are reading (y-dimension).
uint32_t *bitmapPixPtr; // Write pointer for the RGBA8888 bitmap pixel data, relative to the passed in *bitmapData pointer.
if (bitmapData == NULL)
{
return;
}
if (ndsRomHeader == NULL)
{
memset(bitmapData, 0, 4096); // 4096 bytes = 32px * 32px * sizeof(uint32_t)
return;
}
// Set all of our pointers relative to iconOffset.
iconOffset = ndsRomHeader->IconOff;
iconClutPtr = (uint16_t *)&MMU.CART_ROM[iconOffset + 0x220] + 1;
iconPixPtr = (uint32_t *)&MMU.CART_ROM[iconOffset + 0x20];
// Setup the 4-bit color CLUT.
//
// The actual color values are stored with the ROM icon data in RGBA5551 format.
// We convert these color values and store them in the CLUT as RGBA8888 values.
//
// The first entry always represents the alpha, so we can just ignore it.
clut[0] = 0x00000000;
RGBA5551ToRGBA8888Buffer(iconClutPtr, &clut[1], 15);
// Load the image from the icon pixel data.
//
// ROM icons are stored in 4-bit indexed color and have dimensions of 32x32 pixels.
// Also, ROM icons are split into 16 separate 8x8 pixel squares arranged in a 4x4
// array. Here, we sequentially read from the ROM data, and adjust our write
// location appropriately within the bitmap memory block.
for(y = 0; y < 4; y++)
{
for(x = 0; x < 4; x++)
{
for(pixRowIndex = 0; pixRowIndex < 8; pixRowIndex++, iconPixPtr++)
{
// Load the entire row of pixels as a single 32-bit chunk.
pixRowColors = *iconPixPtr;
// Set the write location. The formula below calculates the proper write
// location depending on the position of the read pointer. We use a more
// optimized version of this formula in practice.
//
// bitmapPixPtr = bitmapData + ( ((y * 8) + pixRowIndex) * 32 ) + (x * 8);
bitmapPixPtr = bitmapData + ( ((y << 3) + pixRowIndex) << 5 ) + (x << 3);
// Set the RGBA8888 bitmap pixels using our CLUT from earlier.
#ifdef __BIG_ENDIAN__
*bitmapPixPtr = clut[(pixRowColors & 0x0F000000) >> 24];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0xF0000000) >> 28];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x000F0000) >> 16];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x00F00000) >> 20];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x00000F00) >> 8];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x0000F000) >> 12];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x0000000F)];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x000000F0) >> 4];
#else
*bitmapPixPtr = clut[(pixRowColors & 0x0000000F)];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x000000F0) >> 4];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x00000F00) >> 8];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x0000F000) >> 12];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x000F0000) >> 16];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x00F00000) >> 20];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0x0F000000) >> 24];
bitmapPixPtr++;
*bitmapPixPtr = clut[(pixRowColors & 0xF0000000) >> 28];
#endif
}
}
}
}

View File

@ -0,0 +1,51 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include "videofilter.h"
/********************************************************************************************
CocoaVideoFilter - OBJECTIVE-C CLASS
This is an Objective-C wrapper class for the video filter C++ object.
Thread Safety:
All methods are thread-safe.
********************************************************************************************/
@interface CocoaVideoFilter : NSObject
{
VideoFilter *vf;
}
- (id) initWithSize:(NSSize)theSize;
- (id) initWithSize:(NSSize)theSize typeID:(VideoFilterTypeID)typeID;
- (BOOL) setSourceSize:(NSSize)theSize;
- (BOOL) changeFilter:(VideoFilterTypeID)typeID;
- (UInt32 *) runFilter;
- (NSImage *) image;
- (NSBitmapImageRep *) bitmapImageRep;
- (VideoFilterTypeID) typeID;
- (NSString *) typeString;
- (UInt32 *) srcBufferPtr;
- (UInt32 *) destBufferPtr;
- (NSSize) srcSize;
- (NSSize) destSize;
+ (NSString *) typeStringByID:(VideoFilterTypeID)typeID;
@end

View File

@ -0,0 +1,179 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "cocoa_videofilter.h"
#import "cocoa_util.h"
@implementation CocoaVideoFilter
- (id)init
{
return [self initWithSize:NSMakeSize(1, 1) typeID:VideoFilterTypeID_None];
}
- (id) initWithSize:(NSSize)theSize
{
return [self initWithSize:theSize typeID:VideoFilterTypeID_None];
}
- (id) initWithSize:(NSSize)theSize typeID:(VideoFilterTypeID)typeID
{
self = [super init];
if (self == nil)
{
return self;
}
vf = new VideoFilter((unsigned int)theSize.width, (unsigned int)theSize.height, typeID);
return self;
}
- (void)dealloc
{
delete vf;
[super dealloc];
}
- (BOOL) setSourceSize:(NSSize)theSize
{
BOOL result = NO;
bool cResult = vf->SetSourceSize((unsigned int)theSize.width, (unsigned int)theSize.height);
if (cResult)
{
result = YES;
}
return result;
}
- (BOOL) changeFilter:(VideoFilterTypeID)typeID
{
BOOL result = NO;
bool cResult = vf->ChangeFilter(typeID);
if (cResult)
{
result = YES;
}
return result;
}
- (UInt32 *) runFilter
{
return (UInt32 *)vf->RunFilter();
}
- (NSImage *) image
{
NSImage *newImage = [[NSImage alloc] initWithSize:[self destSize]];
if (newImage == nil)
{
return newImage;
}
NSBitmapImageRep *newImageRep = [self bitmapImageRep];
if (newImageRep == nil)
{
[newImage release];
newImage = nil;
return newImage;
}
[newImage addRepresentation:newImageRep];
return newImage;
}
- (NSBitmapImageRep *) bitmapImageRep
{
NSUInteger w = (NSUInteger)vf->GetDestWidth();
NSUInteger h = (NSUInteger)vf->GetDestHeight();
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:w
pixelsHigh:h
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bytesPerRow:w * 4
bitsPerPixel:32];
if(imageRep == nil)
{
return imageRep;
}
uint32_t *bitmapData = (uint32_t *)[imageRep bitmapData];
RGB888ToRGBA8888Buffer((const uint32_t *)[self runFilter], bitmapData, (w * h));
#ifdef __BIG_ENDIAN__
uint32_t *bitmapDataEnd = bitmapData + (w * h);
while (bitmapData < bitmapDataEnd)
{
*bitmapData++ = CFSwapInt32LittleToHost(*bitmapData);
}
#endif
return [imageRep autorelease];
}
- (VideoFilterTypeID) typeID
{
return vf->GetTypeID();
}
- (NSString *) typeString
{
return [NSString stringWithCString:vf->GetTypeString() encoding:NSUTF8StringEncoding];
}
- (UInt32 *) srcBufferPtr
{
return (UInt32 *)vf->GetSrcBufferPtr();
}
- (UInt32 *) destBufferPtr
{
return (UInt32 *)vf->GetDestBufferPtr();
}
- (NSSize) srcSize
{
return NSMakeSize((CGFloat)vf->GetSrcWidth(), (CGFloat)vf->GetSrcHeight());
}
- (NSSize) destSize
{
return NSMakeSize((CGFloat)vf->GetDestWidth(), (CGFloat)vf->GetDestHeight());
}
+ (NSString *) typeStringByID:(VideoFilterTypeID)typeID
{
const char *vfTypeCString = VideoFilter::GetTypeStringByID(typeID);
NSString *vfTypeString = [NSString stringWithCString:vfTypeCString encoding:NSUTF8StringEncoding];
return vfTypeString;
}
@end

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,104 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class InputPrefsView;
@class CocoaHIDManager;
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
@interface AppDelegate : NSObject <NSApplicationDelegate>
#else
@interface AppDelegate : NSObject
#endif
{
NSObject *dummyObject;
NSArrayController *fileMigrationList;
NSObjectController *aboutWindowController;
NSObjectController *emuWindowController;
NSObjectController *prefWindowController;
NSObjectController *cheatWindowController;
NSObjectController *cdsCoreController;
NSWindow *mainWindow;
NSWindow *prefWindow;
NSWindow *cheatListWindow;
NSWindow *migrationWindow;
NSView *prefGeneralView;
InputPrefsView *inputPrefsView;
NSMenu *mLoadStateSlot;
NSMenu *mSaveStateSlot;
NSBox *boxGeneralInfo;
NSBox *boxTitles;
NSBox *boxARMBinaries;
NSBox *boxFileSystem;
NSBox *boxMisc;
CocoaHIDManager *hidManager;
BOOL migrationFilesPresent;
}
@property (readonly) IBOutlet NSObject *dummyObject;
@property (readonly) IBOutlet NSArrayController *fileMigrationList;
@property (readonly) IBOutlet NSObjectController *aboutWindowController;
@property (readonly) IBOutlet NSObjectController *emuWindowController;
@property (readonly) IBOutlet NSObjectController *prefWindowController;
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
@property (readonly) IBOutlet NSObjectController *cdsCoreController;
@property (readonly) IBOutlet NSWindow *mainWindow;
@property (readonly) IBOutlet NSWindow *prefWindow;
@property (readonly) IBOutlet NSWindow *cheatListWindow;
@property (readonly) IBOutlet NSWindow *migrationWindow;
@property (readonly) IBOutlet NSView *prefGeneralView;
@property (readonly) IBOutlet NSMenu *mLoadStateSlot;
@property (readonly) IBOutlet NSMenu *mSaveStateSlot;
@property (readonly) IBOutlet InputPrefsView *inputPrefsView;
@property (readonly) IBOutlet NSBox *boxGeneralInfo;
@property (readonly) IBOutlet NSBox *boxTitles;
@property (readonly) IBOutlet NSBox *boxARMBinaries;
@property (readonly) IBOutlet NSBox *boxFileSystem;
@property (readonly) IBOutlet NSBox *boxMisc;
@property (retain) CocoaHIDManager *hidManager;
@property (assign) BOOL migrationFilesPresent;
// Emulation Menu
// View Menu
// Tools Menu
- (IBAction) showSupportFolderInFinder:(id)sender;
// Help Menu
- (IBAction) launchWebsite:(id)sender;
- (IBAction) launchForums:(id)sender;
- (IBAction) bugReport:(id)sender;
- (void) setupSlotMenuItems;
- (NSMenuItem *) addSlotMenuItem:(NSMenu *)menu slotNumber:(NSUInteger)slotNumber;
- (void) setupUserDefaults;
- (void) updateInputDisplayFields;
- (IBAction) showMigrationWindow:(id)sender;
- (IBAction) handleMigrationWindow:(id)sender;
- (void) setRomInfoPanelBoxTitleColors;
@end

View File

@ -0,0 +1,589 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "appDelegate.h"
#import "emuWindowDelegate.h"
#import "preferencesWindowDelegate.h"
#import "cheatWindowDelegate.h"
#import "displayView.h"
#import "inputPrefsView.h"
#import "cocoa_core.h"
#import "cocoa_file.h"
#import "cocoa_firmware.h"
#import "cocoa_globals.h"
#import "cocoa_hid.h"
#import "cocoa_input.h"
#import "cocoa_mic.h"
@implementation AppDelegate
@dynamic dummyObject;
@synthesize mainWindow;
@synthesize prefWindow;
@synthesize cheatListWindow;
@synthesize migrationWindow;
@synthesize prefGeneralView;
@synthesize mLoadStateSlot;
@synthesize mSaveStateSlot;
@synthesize inputPrefsView;
@synthesize fileMigrationList;
@synthesize aboutWindowController;
@synthesize emuWindowController;
@synthesize prefWindowController;
@synthesize cdsCoreController;
@synthesize cheatWindowController;
@synthesize boxGeneralInfo;
@synthesize boxTitles;
@synthesize boxARMBinaries;
@synthesize boxFileSystem;
@synthesize boxMisc;
@synthesize hidManager;
@synthesize migrationFilesPresent;
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
BOOL result = NO;
NSURL *fileURL = [NSURL fileURLWithPath:filename];
EmuWindowDelegate *mainWindowDelegate = [mainWindow delegate];
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
if (cdsCore == nil)
{
return result;
}
NSString *fileKind = [CocoaDSFile fileKindByURL:fileURL];
if ([fileKind isEqualToString:@"ROM"])
{
result = [mainWindowDelegate handleLoadRom:fileURL];
if ([mainWindowDelegate isShowingSaveStateSheet] || [mainWindowDelegate isShowingFileMigrationSheet])
{
// Just reply YES if a sheet is showing, even if the ROM hasn't actually been loaded yet.
// This will prevent the error dialog from showing, which is the intended behavior in
// this case.
result = YES;
}
}
return result;
}
- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
EmuWindowDelegate *mainWindowDelegate = [mainWindow delegate];
PreferencesWindowDelegate *prefWindowDelegate = [prefWindow delegate];
CheatWindowDelegate *cheatWindowDelegate = [cheatListWindow delegate];
// Create the needed directories in Application Support if they haven't already
// been created.
if (![CocoaDSFile setupAllAppDirectories])
{
// Need to show a modal dialog here.
return;
}
[CocoaDSFile setupAllFilePaths];
// Setup the About window.
NSMutableDictionary *aboutWindowProperties = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[[NSBundle mainBundle] pathForResource:@FILENAME_README ofType:@""], @"readMePath",
[[NSBundle mainBundle] pathForResource:@FILENAME_COPYING ofType:@""], @"licensePath",
[[NSBundle mainBundle] pathForResource:@FILENAME_AUTHORS ofType:@""], @"authorsPath",
[[NSBundle mainBundle] pathForResource:@FILENAME_CHANGELOG ofType:@""], @"changeLogPath",
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"], @"versionString",
@__DATE__, @"dateString",
nil];
[aboutWindowController setContent:aboutWindowProperties];
// Register the application's defaults.
NSDictionary *prefsDict = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DefaultUserPrefs" ofType:@"plist"]];
if (prefsDict == nil)
{
[[NSAlert alertWithMessageText:NSSTRING_ALERT_CRITICAL_FILE_MISSING_PRI defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:NSSTRING_ALERT_CRITICAL_FILE_MISSING_SEC] runModal];
[NSApp terminate: nil];
return;
}
[[NSUserDefaults standardUserDefaults] registerDefaults:prefsDict];
// Change the title colors of the NSBox objects in the ROM Info panel. We change the
// colors manually here because you can't change them in Interface Builder. Boo!!!
[self setRomInfoPanelBoxTitleColors];
// Set up all the object controllers according to our default windows.
[emuWindowController setContent:[mainWindowDelegate bindings]];
[prefWindowController setContent:[prefWindowDelegate bindings]];
[cheatWindowController setContent:[cheatWindowDelegate bindings]];
// Set the preferences window to the general view by default.
[prefWindowDelegate switchContentView:prefGeneralView];
// Setup the slot menu items. We set this up manually instead of through Interface
// Builder because we're assuming an arbitrary number of slot items.
[self setupSlotMenuItems];
// Setup the HID Input manager.
[self setHidManager:[[[CocoaHIDManager alloc] init] autorelease]];
// Set the display view delegate.
DisplayViewDelegate *newDispViewDelegate = [[DisplayViewDelegate alloc] init];
[newDispViewDelegate setView:[mainWindowDelegate displayView]];
[mainWindowDelegate setDispViewDelegate:newDispViewDelegate];
[[mainWindowDelegate displayView] setDispViewDelegate:newDispViewDelegate];
// Init the DS emulation core.
CocoaDSCore *newCore = [[[CocoaDSCore alloc] init] autorelease];
[cdsCoreController setContent:newCore];
// Init the DS controller and microphone.
CocoaDSController *newController = [[[CocoaDSController alloc] init] autorelease];
[newCore setCdsController:newController];
[inputPrefsView setCdsController:newController];
[newDispViewDelegate setCdsController:newController];
// Init the DS displays.
CocoaDSDisplay *newComboDisplay = [[[CocoaDSDisplay alloc] init] autorelease];
[newComboDisplay setDelegate:newDispViewDelegate];
[newCore addOutput:newComboDisplay];
NSPort *guiPort = [NSPort port];
[[NSRunLoop currentRunLoop] addPort:guiPort forMode:NSDefaultRunLoopMode];
// Init the DS speakers.
CocoaDSSpeaker *newSpeaker = [[[CocoaDSSpeaker alloc] init] autorelease];
[newCore addOutput:newSpeaker];
[mainWindowDelegate setCdsSpeaker:newSpeaker];
// Start the core thread.
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newCore withObject:nil];
// Wait until the emulation core has finished starting up.
while (!([CocoaDSCore isCoreStarted] && [newCore thread] != nil))
{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
// Start up the threads for our outputs.
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newComboDisplay withObject:nil];
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newSpeaker withObject:nil];
// Wait until the GPU and SPU are finished starting up.
while (!([CocoaDSSpeaker isSPUStarted] &&
[newComboDisplay thread] != nil && [newSpeaker thread] != nil))
{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
// Setup the applications settings from the user defaults file.
[self setupUserDefaults];
// Setup the window display view.
[[mainWindowDelegate displayView] setNextResponder:mainWindow];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
EmuWindowDelegate *mainWindowDelegate = [mainWindow delegate];
// Load a new ROM on launch per user preferences.
BOOL loadROMOnLaunch = [[NSUserDefaults standardUserDefaults] boolForKey:@"General_AutoloadROMOnLaunch"];
if (loadROMOnLaunch && ![mainWindowDelegate isRomLoaded])
{
NSInteger autoloadRomOption = [[NSUserDefaults standardUserDefaults] integerForKey:@"General_AutoloadROMOption"];
NSURL *autoloadRomURL = nil;
if (autoloadRomOption == ROMAUTOLOADOPTION_LOAD_LAST)
{
autoloadRomURL = [CocoaDSFile lastLoadedRomURL];
}
else if(autoloadRomOption == ROMAUTOLOADOPTION_LOAD_SELECTED)
{
NSString *autoloadRomPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"General_AutoloadROMSelectedPath"];
if (autoloadRomPath != nil && [autoloadRomPath length] > 0)
{
autoloadRomURL = [NSURL fileURLWithPath:autoloadRomPath];
}
}
if (autoloadRomURL != nil)
{
[mainWindowDelegate handleLoadRom:autoloadRomURL];
}
}
// Make the display view black.
[[mainWindowDelegate dispViewDelegate] setViewToBlack];
//Bring the application to the front
[NSApp activateIgnoringOtherApps:TRUE];
[mainWindow makeKeyAndOrderFront:nil];
[mainWindow makeMainWindow];
// Present the file migration window to the user (if they haven't disabled it).
[self setMigrationFilesPresent:NO];
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"General_DoNotAskMigrate"])
{
[self showMigrationWindow:nil];
}
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
EmuWindowDelegate *mainWindowDelegate = [mainWindow delegate];
// If a file needs to be saved, give the user a chance to save it
// before quitting.
BOOL didRomClose = [mainWindowDelegate handleUnloadRom:REASONFORCLOSE_TERMINATE romToLoad:nil];
if (!didRomClose)
{
if ([mainWindowDelegate isShowingSaveStateSheet])
{
return NSTerminateLater;
}
}
// Either there wasn't a file that needed to be saved, or there
// wasn't anything loaded. Just continue program termination normally.
return NSTerminateNow;
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
if (cdsCore != nil)
{
[cdsCore setCoreState:CORESTATE_PAUSE];
[cdsCore removeAllOutputs];
[cdsCoreController setContent:nil];
}
}
- (IBAction) showSupportFolderInFinder:(id)sender
{
NSURL *folderURL = [CocoaDSFile userAppSupportBaseURL];
[[NSWorkspace sharedWorkspace] openFile:[folderURL path] withApplication:@"Finder"];
}
- (IBAction) launchWebsite:(id)sender
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@STRING_DESMUME_WEBSITE]];
}
- (IBAction) launchForums:(id)sender
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@STRING_DESMUME_FORUM_SITE]];
}
- (IBAction) bugReport:(id)sender
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@STRING_DESMUME_BUG_SITE]];
}
- (void) setupSlotMenuItems
{
NSInteger i;
NSMenuItem *loadItem = nil;
NSMenuItem *saveItem = nil;
for(i = 0; i < MAX_SAVESTATE_SLOTS; i++)
{
loadItem = [self addSlotMenuItem:mLoadStateSlot slotNumber:(NSUInteger)(i + 1)];
[loadItem setKeyEquivalentModifierMask:0];
[loadItem setTag:i];
[loadItem setAction:@selector(loadEmuSaveStateSlot:)];
saveItem = [self addSlotMenuItem:mSaveStateSlot slotNumber:(NSUInteger)(i + 1)];
[saveItem setKeyEquivalentModifierMask:NSShiftKeyMask];
[saveItem setTag:i];
[saveItem setAction:@selector(saveEmuSaveStateSlot:)];
}
}
- (NSMenuItem *) addSlotMenuItem:(NSMenu *)menu slotNumber:(NSUInteger)slotNumber
{
NSUInteger slotNumberKey = slotNumber;
if (slotNumber == 10)
{
slotNumberKey = 0;
}
NSMenuItem *mItem = [menu addItemWithTitle:[NSString stringWithFormat:NSSTRING_TITLE_SLOT_NUMBER, slotNumber]
action:nil
keyEquivalent:[NSString stringWithFormat:@"%d", slotNumberKey]];
[mItem setTarget:[mainWindow delegate]];
return mItem;
}
- (void) setupUserDefaults
{
EmuWindowDelegate *mainWindowDelegate = [mainWindow delegate];
PreferencesWindowDelegate *prefWindowDelegate = [prefWindow delegate];
NSMutableDictionary *prefBindings = [prefWindowDelegate bindings];
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
// Set the emulation flags.
NSUInteger emuFlags = 0;
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Emulation_AdvancedBusLevelTiming"])
{
emuFlags |= EMULATION_ADVANCED_BUS_LEVEL_TIMING_MASK;
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Emulation_UseExternalBIOSImages"])
{
emuFlags |= EMULATION_USE_EXTERNAL_BIOS_MASK;
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Emulation_BIOSEmulateSWI"])
{
emuFlags |= EMULATION_BIOS_SWI_MASK;
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Emulation_BIOSPatchDelayLoopSWI"])
{
emuFlags |= EMULATION_PATCH_DELAY_LOOP_MASK;
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Emulation_UseExternalFirmwareImage"])
{
emuFlags |= EMULATION_USE_EXTERNAL_FIRMWARE_MASK;
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Emulation_FirmwareBoot"])
{
emuFlags |= EMULATION_BOOT_FROM_FIRMWARE_MASK;
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Emulation_EmulateEnsata"])
{
emuFlags |= EMULATION_ENSATA_MASK;
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Emulation_UseDebugConsole"])
{
emuFlags |= EMULATION_DEBUG_CONSOLE_MASK;
}
[cdsCore setEmulationFlags:emuFlags];
// Set up the firmware per user preferences.
NSMutableDictionary *newFWDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[[NSUserDefaults standardUserDefaults] objectForKey:@"FirmwareConfig_Nickname"], @"Nickname",
[[NSUserDefaults standardUserDefaults] objectForKey:@"FirmwareConfig_Message"], @"Message",
[[NSUserDefaults standardUserDefaults] objectForKey:@"FirmwareConfig_FavoriteColor"], @"FavoriteColor",
[[NSUserDefaults standardUserDefaults] objectForKey:@"FirmwareConfig_Birthday"], @"Birthday",
[[NSUserDefaults standardUserDefaults] objectForKey:@"FirmwareConfig_Language"], @"Language",
nil];
CocoaDSFirmware *newFirmware = [[CocoaDSFirmware alloc] initWithDictionary:newFWDict];
[cdsCore setCdsFirmware:newFirmware];
[newFirmware update];
// Setup the ARM7 BIOS, ARM9 BIOS, and firmware image paths per user preferences.
NSString *arm7BiosImagePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"BIOS_ARM7ImagePath"];
if (arm7BiosImagePath != nil)
{
[cdsCore setArm7ImageURL:[NSURL fileURLWithPath:arm7BiosImagePath]];
[prefBindings setValue:[arm7BiosImagePath lastPathComponent] forKey:@"Arm7BiosImageName"];
}
else
{
[cdsCore setArm7ImageURL:nil];
[prefBindings setValue:nil forKey:@"Arm7BiosImageName"];
}
NSString *arm9BiosImagePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"BIOS_ARM9ImagePath"];
if (arm9BiosImagePath != nil)
{
[cdsCore setArm9ImageURL:[NSURL fileURLWithPath:arm9BiosImagePath]];
[prefBindings setValue:[arm9BiosImagePath lastPathComponent] forKey:@"Arm9BiosImageName"];
}
else
{
[cdsCore setArm9ImageURL:nil];
[prefBindings setValue:nil forKey:@"Arm9BiosImageName"];
}
NSString *firmwareImagePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"Emulation_FirmwareImagePath"];
if (firmwareImagePath != nil)
{
[cdsCore setFirmwareImageURL:[NSURL fileURLWithPath:firmwareImagePath]];
[prefBindings setValue:[firmwareImagePath lastPathComponent] forKey:@"FirmwareImageName"];
}
else
{
[cdsCore setFirmwareImageURL:nil];
[prefBindings setValue:nil forKey:@"FirmwareImageName"];
}
NSString *advansceneDatabasePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"Advanscene_DatabasePath"];
if (advansceneDatabasePath != nil)
{
[prefBindings setValue:[advansceneDatabasePath lastPathComponent] forKey:@"AdvansceneDatabaseName"];
}
NSString *cheatDatabasePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
if (cheatDatabasePath != nil)
{
[prefBindings setValue:[cheatDatabasePath lastPathComponent] forKey:@"R4CheatDatabaseName"];
}
// Set the sound input mode per user preferences.
[[cdsCore cdsController] setSoundInputMode:[[NSUserDefaults standardUserDefaults] integerForKey:@"Input_AudioInputMode"]];
// Update the SPU Sync controls in the Preferences window.
if ([[NSUserDefaults standardUserDefaults] integerForKey:@"SPU_SyncMode"] == SPU_SYNC_MODE_DUAL_SYNC_ASYNC)
{
[[prefWindowDelegate spuSyncMethodMenu] setEnabled:NO];
}
else
{
[[prefWindowDelegate spuSyncMethodMenu] setEnabled:YES];
}
// Set the text field for the autoloaded ROM.
NSString *autoloadRomPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"General_AutoloadROMSelectedPath"];
if (autoloadRomPath != nil)
{
[prefBindings setValue:[autoloadRomPath lastPathComponent] forKey:@"AutoloadRomName"];
}
else
{
[prefBindings setValue:nil forKey:@"AutoloadRomName"];
}
// Update all of the input display fields.
[self updateInputDisplayFields];
// Set the menu for the display rotation.
double displayRotation = (double)[[NSUserDefaults standardUserDefaults] floatForKey:@"DisplayView_Rotation"];
[prefWindowDelegate updateDisplayRotationMenu:displayRotation];
// Set the default sound volume per user preferences.
[prefWindowDelegate updateVolumeIcon:nil];
[mainWindowDelegate setupUserDefaults];
}
- (void) updateInputDisplayFields
{
PreferencesWindowDelegate *prefWindowDelegate = [prefWindow delegate];
NSMutableDictionary *prefBindings = [prefWindowDelegate bindings];
if ([[NSUserDefaults standardUserDefaults] dictionaryForKey:@"Input_ControllerMappings"] == nil)
{
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"];
}
- (IBAction) showMigrationWindow:(id)sender
{
NSMutableArray *fileList = [CocoaDSFile completeFileList];
if (fileList != nil)
{
if ([fileList count] == 0)
{
[self setMigrationFilesPresent:NO];
}
else
{
[self setMigrationFilesPresent:YES];
}
if (sender == nil && ![self migrationFilesPresent])
{
return;
}
}
[fileMigrationList setContent:fileList];
[migrationWindow center];
[migrationWindow makeKeyAndOrderFront:nil];
}
- (IBAction) handleMigrationWindow:(id)sender
{
NSInteger option = [(NSControl *)sender tag];
NSMutableArray *fileList = [fileMigrationList content];
switch (option)
{
case COCOA_DIALOG_DEFAULT:
[CocoaDSFile copyFileListToCurrent:fileList];
break;
case COCOA_DIALOG_OPTION:
[CocoaDSFile moveFileListToCurrent:fileList];
break;
default:
break;
}
[[(NSControl *)sender window] close];
}
- (void) setRomInfoPanelBoxTitleColors
{
NSColor *boxTitleColor = [NSColor whiteColor];
[[boxGeneralInfo titleCell] setTextColor:boxTitleColor];
[[boxTitles titleCell] setTextColor:boxTitleColor];
[[boxARMBinaries titleCell] setTextColor:boxTitleColor];
[[boxFileSystem titleCell] setTextColor:boxTitleColor];
[[boxMisc titleCell] setTextColor:boxTitleColor];
[boxGeneralInfo setNeedsDisplay:YES];
[boxTitles setNeedsDisplay:YES];
[boxARMBinaries setNeedsDisplay:YES];
[boxFileSystem setNeedsDisplay:YES];
[boxMisc setNeedsDisplay:YES];
}
@end

View File

@ -0,0 +1,122 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class CocoaDSCheatItem;
@class CocoaDSCheatManager;
@class CocoaDSCheatSearch;
@class CocoaDSCheatSearchParams;
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
@interface CheatWindowDelegate : NSObject <NSWindowDelegate, NSTableViewDelegate>
#else
@interface CheatWindowDelegate : NSObject
#endif
{
NSObject *dummyObject;
NSWindow *window;
NSBox *cheatConfigBox;
NSView *cheatSearchView;
NSTableView *cheatListTable;
NSTableView *cheatSearchListTable;
NSArrayController *cheatListController;
NSArrayController *cheatSearchListController;
NSArrayController *cheatDatabaseController;
NSObjectController *cheatWindowController;
NSObjectController *cheatSelectedItemController;
NSView *currentView;
NSView *viewConfigureNoSelection;
NSView *viewConfigureInternalCheat;
NSView *viewConfigureActionReplayCheat;
NSView *viewConfigureCodeBreakerCheat;
NSView *currentSearchStyleView;
NSView *viewSearchNoSelection;
NSView *viewSearchExactValue;
NSView *viewSearchComparativeStart;
NSView *viewSearchComparativeContinue;
NSSearchField *searchField;
NSWindow *cheatDatabaseSheet;
NSUInteger untitledCount;
NSMutableDictionary *bindings;
CocoaDSCheatItem *workingCheat;
CocoaDSCheatManager *cdsCheats;
CocoaDSCheatSearch *cdsCheatSearch;
}
@property (assign) IBOutlet NSObject *dummyObject;
@property (readonly) IBOutlet NSWindow *window;
@property (readonly) IBOutlet NSBox *cheatConfigBox;
@property (readonly) IBOutlet NSView *cheatSearchView;
@property (readonly) IBOutlet NSTableView *cheatListTable;
@property (readonly) IBOutlet NSTableView *cheatSearchListTable;
@property (readonly) IBOutlet NSArrayController *cheatListController;
@property (readonly) IBOutlet NSArrayController *cheatSearchListController;
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
@property (readonly) IBOutlet NSObjectController *cheatSelectedItemController;
@property (readonly) IBOutlet NSView *viewConfigureNoSelection;
@property (readonly) IBOutlet NSView *viewConfigureInternalCheat;
@property (readonly) IBOutlet NSView *viewConfigureActionReplayCheat;
@property (readonly) IBOutlet NSView *viewConfigureCodeBreakerCheat;
@property (readonly) IBOutlet NSView *viewSearchNoSelection;
@property (readonly) IBOutlet NSView *viewSearchExactValue;
@property (readonly) IBOutlet NSView *viewSearchComparativeStart;
@property (readonly) IBOutlet NSView *viewSearchComparativeContinue;
@property (readonly) IBOutlet NSSearchField *searchField;
@property (readonly) IBOutlet NSWindow *cheatDatabaseSheet;
@property (assign) NSUInteger untitledCount;
@property (assign) NSMutableDictionary *bindings;
@property (assign) CocoaDSCheatItem *workingCheat;
@property (assign) CocoaDSCheatManager *cdsCheats;
@property (assign) CocoaDSCheatSearch *cdsCheatSearch;
- (IBAction) addToList:(id)sender;
- (IBAction) removeFromList:(id)sender;
- (IBAction) viewDatabase:(id)sender;
- (IBAction) setInternalCheatValue:(id)sender;
- (IBAction) applyConfiguration:(id)sender;
- (IBAction) selectCheatType:(id)sender;
- (IBAction) selectCheatSearchStyle:(id)sender;
- (IBAction) runExactValueSearch:(id)sender;
- (IBAction) runComparativeSearch:(id)sender;
- (void) searchDidFinish:(NSNotification *)aNotification;
- (IBAction) resetSearch:(id)sender;
- (void) setCheatConfigViewByType:(NSInteger)cheatTypeID;
- (void) setCheatSearchViewByStyle:(NSInteger)searchStyleID;
- (IBAction) selectAllCheatsInDatabase:(id)sender;
- (IBAction) selectNoneCheatsInDatabase:(id)sender;
- (void) addSelectedFromCheatDatabase;
- (IBAction) closeCheatDatabaseSheet:(id)sender;
- (void) didEndCheatDatabaseSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
@end

View File

@ -0,0 +1,538 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "cheatWindowDelegate.h"
#import "cocoa_globals.h"
#import "cocoa_cheat.h"
#import "cocoa_util.h"
@implementation CheatWindowDelegate
@dynamic dummyObject;
@synthesize window;
@synthesize cheatConfigBox;
@synthesize cheatSearchView;
@synthesize cheatListTable;
@synthesize cheatSearchListTable;
@synthesize cheatListController;
@synthesize cheatSearchListController;
@synthesize cheatDatabaseController;
@synthesize cheatWindowController;
@synthesize cheatSelectedItemController;
@synthesize viewConfigureNoSelection;
@synthesize viewConfigureInternalCheat;
@synthesize viewConfigureActionReplayCheat;
@synthesize viewConfigureCodeBreakerCheat;
@synthesize viewSearchNoSelection;
@synthesize viewSearchExactValue;
@synthesize viewSearchComparativeStart;
@synthesize viewSearchComparativeContinue;
@synthesize searchField;
@synthesize cheatDatabaseSheet;
@synthesize untitledCount;
@synthesize bindings;
@synthesize cdsCheats;
@synthesize cdsCheatSearch;
@synthesize workingCheat;
- (id)init
{
self = [super init];
if(self == nil)
{
return nil;
}
bindings = [[NSMutableDictionary alloc] init];
if (bindings == nil)
{
[self release];
self = nil;
return self;
}
cdsCheatSearch = [[CocoaDSCheatSearch alloc] init];
if (cdsCheatSearch == nil)
{
[bindings release];
[self release];
self = nil;
return self;
}
workingCheat = nil;
currentView = nil;
currentSearchStyleView = nil;
untitledCount = 0;
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasSelection"];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasItems"];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isRunningSearch"];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isSearchStarted"];
[bindings setValue:[NSNumber numberWithInteger:CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE] forKey:@"cheatSearchStyle"];
[bindings setValue:[NSNumber numberWithInteger:CHEATSEARCH_UNSIGNED] forKey:@"cheatSearchSignType"];
[bindings setValue:@"Search not started." forKey:@"cheatSearchAddressCount"];
return self;
}
- (void)dealloc
{
[cdsCheatSearch release];
[bindings release];
[super dealloc];
}
- (IBAction) addToList:(id)sender
{
if (self.cdsCheats == nil)
{
return;
}
NSString *untitledString = nil;
self.untitledCount++;
if (self.untitledCount > 1)
{
untitledString = [NSString stringWithFormat:@"Untitled %d", self.untitledCount];
}
else
{
untitledString = @"Untitled";
}
CocoaDSCheatItem *newCheatItem = [[[CocoaDSCheatItem alloc] init] autorelease];
newCheatItem.cheatType = CHEAT_TYPE_INTERNAL;
newCheatItem.description = untitledString;
[cheatListController addObject:newCheatItem];
[self.cdsCheats add:newCheatItem];
[self.cdsCheats save];
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"hasItems"];
}
- (IBAction) removeFromList:(id)sender
{
NSMutableArray *cheatList = (NSMutableArray *)[cheatListController content];
if (cdsCheats == nil || cheatList == nil)
{
return;
}
NSUInteger selectionIndex = [cheatListController selectionIndex];
if (selectionIndex == NSNotFound)
{
return;
}
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:selectionIndex];
NSArray *selectedObjects = [cheatListController selectedObjects];
CocoaDSCheatItem *selectedCheat = (CocoaDSCheatItem *)[selectedObjects objectAtIndex:0];
[self.cdsCheats remove:selectedCheat];
[cheatListController removeObject:selectedCheat];
[self.cdsCheats save];
[cheatListTable deselectAll:sender];
NSUInteger cheatCount = [cheatList count];
if (cheatCount > 0)
{
if (selectionIndex >= cheatCount)
{
selectionIndex--;
indexSet = [NSIndexSet indexSetWithIndex:selectionIndex];
}
[cheatListTable selectRowIndexes:indexSet byExtendingSelection:NO];
}
else
{
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasItems"];
}
}
- (IBAction) viewDatabase:(id)sender
{
[NSApp beginSheet:cheatDatabaseSheet
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(didEndCheatDatabaseSheet:returnCode:contextInfo:)
contextInfo:nil];
}
- (IBAction) setInternalCheatValue:(id)sender
{
// Force end of editing of any text fields.
[window makeFirstResponder:nil];
[self.cdsCheats applyInternalCheat:self.workingCheat];
}
- (IBAction) applyConfiguration:(id)sender
{
if (self.workingCheat == nil)
{
return;
}
// Force end of editing of any text fields.
[window makeFirstResponder:nil];
[self.workingCheat mergeToParent];
BOOL result = [self.cdsCheats update:self.workingCheat.parent];
if (result)
{
[self.cdsCheats save];
}
else
{
// TODO: Display an error sheet saying that the cheat applying failed.
}
}
- (IBAction) selectCheatType:(id)sender
{
NSInteger cheatTypeID = [CocoaDSUtil getIBActionSenderTag:sender];
CocoaDSCheatItem *cheatItem = [cheatSelectedItemController content];
cheatItem.cheatType = cheatTypeID;
[self setCheatConfigViewByType:cheatTypeID];
}
- (IBAction) selectCheatSearchStyle:(id)sender
{
NSInteger searchStyle = [CocoaDSUtil getIBActionSenderTag:sender];
[self.bindings setValue:[NSNumber numberWithInteger:searchStyle] forKey:@"cheatSearchStyle"];
[self setCheatSearchViewByStyle:searchStyle];
}
- (IBAction) runExactValueSearch:(id)sender
{
if (self.workingCheat == nil)
{
return;
}
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"isSearchStarted"];
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"isRunningSearch"];
NSInteger value = [searchField integerValue];
UInt8 byteSize = self.workingCheat.bytes;
NSInteger signType = [(NSNumber *)[self.bindings valueForKey:@"cheatSearchSignType"] integerValue];
NSUInteger addressCount = [cdsCheatSearch runExactValueSearch:value byteSize:byteSize signType:signType];
[bindings setValue:[NSNumber numberWithUnsignedInteger:addressCount] forKey:@"cheatSearchAddressCount"];
[cheatSearchListController setContent:cdsCheatSearch.addressList];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isRunningSearch"];
}
- (IBAction) runComparativeSearch:(id)sender
{
if (self.workingCheat == nil)
{
return;
}
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"isSearchStarted"];
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"isRunningSearch"];
if (cdsCheatSearch.searchCount == 0)
{
[bindings setValue:@"Running initial search..." forKey:@"cheatSearchAddressCount"];
[window displayIfNeeded];
}
NSInteger compSearchTypeID = [CocoaDSUtil getIBActionSenderTag:sender];
UInt8 byteSize = self.workingCheat.bytes;
NSInteger signType = [(NSNumber *)[self.bindings valueForKey:@"cheatSearchSignType"] integerValue];
NSUInteger addressCount = [cdsCheatSearch runComparativeSearch:compSearchTypeID byteSize:byteSize signType:signType];
[bindings setValue:[NSNumber numberWithUnsignedInteger:addressCount] forKey:@"cheatSearchAddressCount"];
[cheatSearchListController setContent:cdsCheatSearch.addressList];
NSInteger searchStyle = [(NSNumber *)[self.bindings valueForKey:@"cheatSearchStyle"] integerValue];
if (searchStyle == CHEATSEARCH_SEARCHSTYLE_COMPARATIVE && cdsCheatSearch.searchCount == 1)
{
[self setCheatSearchViewByStyle:CHEATSEARCH_SEARCHSTYLE_COMPARATIVE];
[bindings setValue:@"Search started!" forKey:@"cheatSearchAddressCount"];
}
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isRunningSearch"];
}
- (void) searchDidFinish:(NSNotification *)aNotification
{
CocoaDSCheatSearch *searcher = [aNotification object];
NSInteger addressCount = 0;
if (searcher != nil)
{
addressCount = searcher.addressList.count;
[bindings setValue:[NSNumber numberWithUnsignedInteger:addressCount] forKey:@"cheatSearchAddressCount"];
[cheatSearchListController setContent:searcher.addressList];
NSInteger searchStyle = [(NSNumber *)[self.bindings valueForKey:@"cheatSearchStyle"] integerValue];
if (searchStyle == CHEATSEARCH_SEARCHSTYLE_COMPARATIVE && searcher.searchCount == 1)
{
[self setCheatSearchViewByStyle:CHEATSEARCH_SEARCHSTYLE_COMPARATIVE];
[bindings setValue:@"Search started!" forKey:@"cheatSearchAddressCount"];
}
}
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isRunningSearch"];
}
- (IBAction) resetSearch:(id)sender
{
[cheatSearchListController setContent:nil];
[cdsCheatSearch reset];
[self.bindings setValue:nil forKey:@"cheatSearchSearchValue"];
[self.bindings setValue:@"Search not started." forKey:@"cheatSearchAddressCount"];
[self setCheatSearchViewByStyle:[(NSNumber *)[self.bindings valueForKey:@"cheatSearchStyle"] integerValue]];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isSearchStarted"];
}
- (void) setCheatConfigViewByType:(NSInteger)cheatTypeID
{
NSView *newView = nil;
if (currentView == nil)
{
currentView = viewConfigureNoSelection;
}
switch (cheatTypeID)
{
case CHEAT_TYPE_INTERNAL:
newView = viewConfigureInternalCheat;
break;
case CHEAT_TYPE_ACTION_REPLAY:
newView = viewConfigureActionReplayCheat;
break;
case CHEAT_TYPE_CODE_BREAKER:
newView = viewConfigureCodeBreakerCheat;
break;
default:
break;
}
if (newView != nil)
{
NSRect frameRect = [currentView frame];
[currentView retain];
[cheatConfigBox replaceSubview:currentView with:newView];
currentView = newView;
[currentView setFrame:frameRect];
}
}
- (void) setCheatSearchViewByStyle:(NSInteger)searchStyleID
{
NSView *newView = nil;
if (currentSearchStyleView == nil)
{
currentSearchStyleView = viewSearchNoSelection;
}
switch (searchStyleID)
{
case CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE:
newView = viewSearchExactValue;
break;
case CHEATSEARCH_SEARCHSTYLE_COMPARATIVE:
if (cdsCheatSearch.searchCount == 0)
{
newView = viewSearchComparativeStart;
}
else
{
newView = viewSearchComparativeContinue;
}
break;
default:
break;
}
if (newView != nil)
{
NSRect frameRect = [currentSearchStyleView frame];
[currentSearchStyleView retain];
[cheatSearchView replaceSubview:currentSearchStyleView with:newView];
currentSearchStyleView = newView;
[currentSearchStyleView setFrame:frameRect];
}
}
- (IBAction) selectAllCheatsInDatabase:(id)sender
{
NSMutableArray *dbList = [cheatDatabaseController content];
if (dbList == nil)
{
return;
}
for (CocoaDSCheatItem *cheatItem in dbList)
{
cheatItem.willAdd = YES;
}
}
- (IBAction) selectNoneCheatsInDatabase:(id)sender
{
NSMutableArray *dbList = [cheatDatabaseController content];
if (dbList == nil)
{
return;
}
for (CocoaDSCheatItem *cheatItem in dbList)
{
cheatItem.willAdd = NO;
}
}
- (void) addSelectedFromCheatDatabase
{
NSMutableArray *dbList = [cheatDatabaseController content];
if (dbList == nil)
{
return;
}
for (CocoaDSCheatItem *cheatItem in dbList)
{
if (cheatItem.willAdd)
{
CocoaDSCheatItem *newCheatItem = [[[CocoaDSCheatItem alloc] initWithCheatData:cheatItem.data] autorelease];
[newCheatItem retainData];
[cheatListController addObject:newCheatItem];
[self.cdsCheats add:newCheatItem];
}
}
if ([dbList count] > 0)
{
[self.cdsCheats save];
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"hasItems"];
}
}
- (IBAction) closeCheatDatabaseSheet:(id)sender
{
NSWindow *sheet = [(NSControl *)sender window];
NSInteger code = [(NSControl *)sender tag];
[NSApp endSheet:sheet returnCode:code];
}
- (void) didEndCheatDatabaseSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
switch (returnCode)
{
case NSCancelButton:
return;
break;
case NSOKButton:
[self addSelectedFromCheatDatabase];
break;
default:
break;
}
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
[cheatWindowController setContent:self.bindings];
}
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
NSTableView *table = (NSTableView *)[aNotification object];
NSInteger rowIndex = [table selectedRow];
if (table == self.cheatListTable)
{
if (rowIndex >= 0)
{
NSArray *selectedObjects = [cheatListController selectedObjects];
CocoaDSCheatItem *selectedCheat = [selectedObjects objectAtIndex:0];
self.workingCheat = [selectedCheat createWorkingCopy];
[cheatSelectedItemController setContent:self.workingCheat];
[self setCheatConfigViewByType:selectedCheat.cheatType];
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"hasSelection"];
}
else
{
if (self.workingCheat != nil)
{
[self.workingCheat.parent destroyWorkingCopy];
}
[cheatSelectedItemController setContent:nil];
self.workingCheat = nil;
NSRect frameRect = [currentView frame];
[currentView retain];
[cheatConfigBox replaceSubview:currentView with:viewConfigureNoSelection];
currentView = viewConfigureNoSelection;
[currentView setFrame:frameRect];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasSelection"];
}
}
else if (table == self.cheatSearchListTable)
{
if (rowIndex >= 0)
{
NSArray *selectedObjects = [cheatSearchListController selectedObjects];
NSMutableDictionary *selectedAddress = [selectedObjects objectAtIndex:0];
NSString *addressString = [(NSString *)[selectedAddress valueForKey:@"addressString"] substringFromIndex:4];
if (self.workingCheat != nil)
{
self.workingCheat.memAddressSixDigitString = addressString;
}
}
}
}
@end

View File

@ -0,0 +1,141 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include <OpenGL/OpenGL.h>
#include <libkern/OSAtomic.h>
#import "cocoa_output.h"
@class DisplayViewDelegate;
@class CocoaDSController;
@protocol DisplayViewDelegate
@required
- (void) doInitVideoOutput:(NSDictionary *)properties;
- (void) doProcessVideoFrame:(const void *)videoFrameData frameSize:(NSSize)frameSize;
@property (retain) DisplayViewDelegate *dispViewDelegate;
@optional
- (void) doResizeView:(NSRect)rect;
- (void) doRedraw;
- (void) doDisplayTypeChanged:(NSInteger)displayTypeID;
- (void) doBilinearOutputChanged:(BOOL)useBilinear;
- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID;
@end
@interface DisplayViewDelegate : NSObject <CocoaDSDisplayDelegate>
{
NSView <DisplayViewDelegate> *view;
NSPort *sendPortDisplay;
NSPort *sendPortInput;
CocoaDSController *cdsController;
BOOL isHudEnabled;
BOOL isHudEditingModeEnabled;
NSSize normalSize;
NSMutableDictionary *bindings;
OSSpinLock spinlockGpuStateFlags;
OSSpinLock spinlockDisplayType;
OSSpinLock spinlockNormalSize;
OSSpinLock spinlockScale;
OSSpinLock spinlockRotation;
OSSpinLock spinlockUseBilinearOutput;
}
@property (assign) NSView <DisplayViewDelegate> *view;
@property (assign) NSPort *sendPortInput;
@property (retain) CocoaDSController *cdsController;
@property (readonly) NSSize normalSize;
@property (assign) NSMutableDictionary *bindings;
- (void) setGpuStateFlags:(UInt32)flags;
- (UInt32) gpuStateFlags;
- (void) setScale:(double)s;
- (double) scale;
- (void) setRotation:(double)angleDegrees;
- (double) rotation;
- (void) setUseBilinearOutput:(BOOL)theState;
- (BOOL) useBilinearOutput;
- (void) setDisplayType:(NSInteger)theType;
- (NSInteger) displayType;
- (void) setVideoFilterType:(NSInteger)theType;
- (void) setRender3DRenderingEngine:(NSInteger)methodID;
- (void) setRender3DHighPrecisionColorInterpolation:(BOOL)state;
- (void) setRender3DEdgeMarking:(BOOL)state;
- (void) setRender3DFog:(BOOL)state;
- (void) setRender3DTextures:(BOOL)state;
- (void) setRender3DDepthComparisonThreshold:(NSUInteger)threshold;
- (void) setRender3DThreads:(NSUInteger)numberThreads;
- (void) setRender3DLineHack:(BOOL)state;
- (void) setViewToBlack;
- (void) setViewToWhite;
- (void) requestScreenshot:(NSURL *)fileURL fileType:(NSBitmapImageFileType)fileType;
- (void) copyToPasteboard;
- (BOOL) gpuStateByBit:(UInt32)stateBit;
- (NSPoint) dsPointFromEvent:(NSEvent *)theEvent;
- (NSPoint) convertPointToDS:(NSPoint)clickLoc;
- (BOOL) handleKeyPress:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed;
- (BOOL) handleMouseButton:(NSEvent *)theEvent buttonPressed:(BOOL)buttonPressed;
@end
@interface ImageDisplayView : NSImageView <DisplayViewDelegate>
{
DisplayViewDelegate *dispViewDelegate;
NSImage *imageData;
NSBitmapImageRep *currentImageRep;
}
- (NSBitmapImageRep *) bitmapImageRep:(const void *)videoFrameData imageSize:(NSSize)imageSize;
@end
@interface OpenGLDisplayView : NSOpenGLView <DisplayViewDelegate>
{
DisplayViewDelegate *dispViewDelegate;
NSSize lastFrameSize;
GLint glTexRenderStyle;
GLenum glTexPixelFormat;
GLvoid *glTexBack;
NSSize glTexBackSize;
GLuint drawTexture[1];
}
- (void) drawVideoFrame;
- (void) uploadFrameTexture:(const GLvoid *)frameBytes textureSize:(NSSize)textureSize;
@end
#ifdef __cplusplus
extern "C"
{
#endif
void SetupOpenGLView(GLsizei width, GLsizei height, GLfloat scalar, GLfloat angleDegrees);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@protocol DisplayViewDelegate;
@class CocoaDSRom;
@class CocoaDSSpeaker;
@class CocoaDSCheatManager;
@class DisplayViewDelegate;
@class CheatWindowDelegate;
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
@interface EmuWindowDelegate : NSObject <NSWindowDelegate>
#else
@interface EmuWindowDelegate : NSObject
#endif
{
NSObject *dummyObject;
NSWindow *window;
NSWindow *saveFileMigrationSheet;
NSWindow *saveStatePrecloseSheet;
NSView <DisplayViewDelegate> *displayView;
NSView *exportRomSavePanelAccessoryView;
NSView *saveScreenshotPanelAccessoryView;
CocoaDSRom *currentRom;
CocoaDSSpeaker *cdsSpeaker;
CocoaDSCheatManager *cdsCheats;
CocoaDSCheatManager *dummyCheatList;
DisplayViewDelegate *dispViewDelegate;
CheatWindowDelegate *cheatWindowDelegate;
NSObjectController *romInfoPanelController;
NSObjectController *firmwarePanelController;
NSObjectController *cdsCoreController;
NSObjectController *cdsDisplayController;
NSObjectController *cdsSoundController;
NSObjectController *emuWindowController;
NSObjectController *cheatWindowController;
NSArrayController *cheatListController;
NSArrayController *cheatDatabaseController;
NSImage *iconVolumeFull;
NSImage *iconVolumeTwoThird;
NSImage *iconVolumeOneThird;
NSImage *iconVolumeMute;
NSImage *iconExecute;
NSImage *iconPause;
NSImage *iconSpeedNormal;
NSImage *iconSpeedDouble;
BOOL isRomLoading;
BOOL isSheetControllingExecution;
BOOL isShowingSaveStateSheet;
BOOL isShowingFileMigrationSheet;
BOOL isShowingStatusBar;
NSUInteger statusBarHeight;
NSSize minDisplayViewSize;
BOOL isMinSizeNormal;
NSBitmapImageFileType screenshotFileFormat;
NSURL *currentEmuSaveStateURL;
NSInteger selectedExportRomSaveID;
NSInteger selectedRomSaveTypeID;
NSMutableDictionary *bindings;
}
@property (readonly) IBOutlet NSObject *dummyObject;
@property (readonly) IBOutlet NSWindow *window;
@property (readonly) IBOutlet NSWindow *saveFileMigrationSheet;
@property (readonly) IBOutlet NSWindow *saveStatePrecloseSheet;
@property (readonly) IBOutlet NSView <DisplayViewDelegate> *displayView;
@property (readonly) IBOutlet NSView *exportRomSavePanelAccessoryView;
@property (readonly) IBOutlet NSView *saveScreenshotPanelAccessoryView;
@property (assign) CocoaDSRom *currentRom;
@property (assign) CocoaDSSpeaker *cdsSpeaker;
@property (assign) CocoaDSCheatManager *cdsCheats;
@property (retain) DisplayViewDelegate *dispViewDelegate;
@property (readonly) IBOutlet CheatWindowDelegate *cheatWindowDelegate;
@property (readonly) IBOutlet NSObjectController *romInfoPanelController;
@property (readonly) IBOutlet NSObjectController *firmwarePanelController;
@property (readonly) IBOutlet NSObjectController *cdsCoreController;
@property (readonly) IBOutlet NSObjectController *cdsDisplayController;
@property (readonly) IBOutlet NSObjectController *cdsSoundController;
@property (readonly) IBOutlet NSObjectController *emuWindowController;
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
@property (readonly) IBOutlet NSArrayController *cheatListController;
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
@property (assign) BOOL isSheetControllingExecution;
@property (assign) BOOL isShowingSaveStateSheet;
@property (assign) BOOL isShowingFileMigrationSheet;
@property (assign) NSInteger selectedRomSaveTypeID;
@property (assign) NSMutableDictionary *bindings;
- (void) setContentScalar:(double)s;
- (void) setContentRotation:(double)angleDegrees;
- (double) resizeWithTransform:(NSSize)normalBounds scalar:(double)scalar rotation:(double)angleDegrees;
- (double) maxContentScalar:(NSSize)contentBounds;
- (void) setVolume:(float)vol;
- (float) volume;
- (void) setIsRomLoaded:(BOOL)theState;
- (BOOL) isRomLoaded;
- (void) setStatus:(NSString *)theString;
- (NSString *) status;
// File Menu
- (IBAction) openRom:(id)sender;
- (IBAction) closeRom:(id)sender;
- (IBAction) openEmuSaveState:(id)sender;
- (IBAction) saveEmuSaveState:(id)sender;
- (IBAction) saveEmuSaveStateAs:(id)sender;
- (IBAction) revertEmuSaveState:(id)sender;
- (IBAction) loadEmuSaveStateSlot:(id)sender;
- (IBAction) saveEmuSaveStateSlot:(id)sender;
- (IBAction) importRomSave:(id)sender;
- (IBAction) exportRomSave:(id)sender;
- (IBAction) selectExportRomSaveFormat:(id)sender;
// Edit Menu
- (IBAction) copy:(id)sender;
// Emulation Menu
- (IBAction) speedLimitDisable:(id)sender;
- (IBAction) toggleAutoFrameSkip:(id)sender;
- (IBAction) cheatsDisable:(id)sender;
- (IBAction) ejectCard:(id)sender;
- (IBAction) executeCoreToggle:(id)sender;
- (IBAction) resetCore:(id)sender;
- (IBAction) changeRomSaveType:(id)sender;
// View Menu
- (IBAction) hudDisable:(id)sender;
- (IBAction) toggleKeepMinDisplaySizeAtNormal:(id)sender;
- (IBAction) toggleStatusBar:(id)sender;
// Tools Menu
- (IBAction) selectScreenshotFileFormat:(id)sender;
- (IBAction) saveScreenshotAs:(id)sender;
- (void) saveScreenshotAsFinish:(NSNotification *)aNotification;
- (IBAction) toggleGPUState:(id)sender;
// Help Menu
// Window Elements
- (BOOL) handleLoadRom:(NSURL *)fileURL;
- (BOOL) handleUnloadRom:(NSInteger)reasonID romToLoad:(NSURL *)romURL;
- (BOOL) loadRom:(NSURL *)romURL;
- (void) loadRomDidFinish:(NSNotification *)aNotification;
- (BOOL) unloadRom;
- (void) executeCore;
- (void) pauseCore;
- (void) restoreCoreState;
- (IBAction) changeCoreSpeed:(id)sender;
- (IBAction) changeCoreEmuFlags:(id)sender;
- (IBAction) changeFirmwareSettings:(id)sender;
- (IBAction) changeVolume:(id)sender;
- (IBAction) changeAudioEngine:(id)sender;
- (IBAction) changeSpuAdvancedLogic:(id)sender;
- (IBAction) changeSpuInterpolationMode:(id)sender;
- (IBAction) changeSpuSyncMode:(id)sender;
- (IBAction) changeSpuSyncMethod:(id)sender;
- (IBAction) changeScale:(id)sender;
- (IBAction) changeRotation:(id)sender;
- (IBAction) changeRotationRelative:(id)sender;
- (IBAction) changeBilinearOutput:(id)sender;
- (IBAction) changeDisplayMode:(id)sender;
- (IBAction) changeVideoFilter:(id)sender;
- (IBAction) change3DRenderMethod:(id)sender;
- (IBAction) change3DRenderHighPrecisionColorInterpolation:(id)sender;
- (IBAction) change3DRenderEdgeMarking:(id)sender;
- (IBAction) change3DRenderFog:(id)sender;
- (IBAction) change3DRenderTextures:(id)sender;
- (IBAction) change3DRenderDepthComparisonThreshold:(id)sender;
- (IBAction) change3DRenderThreads:(id)sender;
- (IBAction) change3DRenderLineHack:(id)sender;
- (IBAction) closeMigrationSheet:(id)sender;
- (void) didEndFileMigrationSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
- (void) didEndSaveStateSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
- (void) didEndSaveStateSheetOpen:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
- (void) didEndSaveStateSheetTerminate:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
- (void) setupUserDefaults;
- (IBAction) writeDefaultsDisplayRotation:(id)sender;
- (IBAction) writeDefaultsHUDSettings:(id)sender;
- (IBAction) writeDefaultsVideoOutputSettings:(id)sender;
- (IBAction) writeDefaults3DRenderingSettings:(id)sender;
- (IBAction) writeDefaultsEmulationSettings:(id)sender;
- (IBAction) writeDefaultsSoundSettings:(id)sender;
@end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class CocoaDSController;
@interface InputPrefsView : NSView
{
NSWindow *prefWindow;
NSButton *lastConfigButton;
NSInteger configInput;
NSDictionary *keyNameTable;
CocoaDSController *cdsController;
}
@property (readonly) IBOutlet NSWindow *prefWindow;
@property (assign) NSInteger configInput;
@property (retain) CocoaDSController *cdsController;
- (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

View File

@ -0,0 +1,417 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "inputPrefsView.h"
#import "preferencesWindowDelegate.h"
#import "cocoa_globals.h"
#import "cocoa_input.h"
@implementation InputPrefsView
@synthesize prefWindow;
@synthesize configInput;
@synthesize cdsController;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self == nil)
{
return self;
}
lastConfigButton = nil;
configInput = 0;
keyNameTable = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"KeyNames" ofType:@"plist"]];
cdsController = nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleHIDInput:)
name:@"com.DeSmuME.DeSmuME.hidInputDetected"
object:nil];
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[keyNameTable release];
[super dealloc];
}
- (void)keyDown:(NSEvent *)theEvent
{
NSString *elementCode = [NSString stringWithFormat:@"%d", [theEvent keyCode]];
NSString *elementName = (NSString *)[keyNameTable valueForKey:elementCode];
if (configInput != 0)
{
[self addMappingById:configInput deviceCode:@"NSEventKeyboard" deviceName:@"Keyboard" elementCode:elementCode elementName:elementName];
[self inputButtonCancelConfig];
}
}
- (void)mouseDown:(NSEvent *)theEvent
{
BOOL isHandled = [self handleMouseDown:theEvent];
if (!isHandled)
{
[super mouseDown:theEvent];
}
}
- (void)mouseDragged:(NSEvent *)theEvent
{
[self mouseDown:theEvent];
}
- (void)rightMouseDown:(NSEvent *)theEvent
{
BOOL isHandled = [self handleMouseDown:theEvent];
if (!isHandled)
{
[super rightMouseDown:theEvent];
}
}
- (void)rightMouseDragged:(NSEvent *)theEvent
{
[self rightMouseDown:theEvent];
}
- (void)otherMouseDown:(NSEvent *)theEvent
{
BOOL isHandled = [self handleMouseDown:theEvent];
if (!isHandled)
{
[super otherMouseDown:theEvent];
}
}
- (void)otherMouseDragged:(NSEvent *)theEvent
{
[self otherMouseDown:theEvent];
}
- (BOOL) handleMouseDown:(NSEvent *)mouseEvent
{
BOOL isHandled = NO;
NSString *elementCode = [NSString stringWithFormat:@"%i", [mouseEvent buttonNumber]];
NSString *elementName = [NSString stringWithFormat:@"Button %i", [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;
configInput = [theButton tag];
}
else
{
[self inputButtonCancelConfig];
}
}
- (void) inputButtonCancelConfig
{
if (lastConfigButton != nil)
{
[lastConfigButton setState:NSOffState];
lastConfigButton = nil;
}
configInput = 0;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (BOOL)becomeFirstResponder
{
return YES;
}
- (BOOL)resignFirstResponder
{
return YES;
}
- (void) handleHIDInput:(NSNotification *)aNotification
{
if (configInput == 0)
{
return;
}
NSArray *inputPropertiesList = (NSArray *)[aNotification object];
BOOL inputOn = NO;
for (NSDictionary *inputProperties in inputPropertiesList)
{
NSNumber *onState = (NSNumber *)[inputProperties valueForKey:@"on"];
if (onState != nil)
{
inputOn = [onState boolValue];
if (inputOn)
{
NSString *deviceCode = (NSString *)[inputProperties valueForKey:@"deviceCode"];
NSString *deviceName = (NSString *)[inputProperties valueForKey:@"deviceName"];
NSString *elementCode = (NSString *)[inputProperties valueForKey:@"elementCode"];
NSString *elementName = (NSString *)[inputProperties valueForKey:@"elementName"];
[self addMappingById:configInput deviceCode:deviceCode deviceName:deviceName elementCode:elementCode elementName:elementName];
[self inputButtonCancelConfig];
break;
}
}
}
}
@end

View File

@ -0,0 +1,126 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class InputPrefsView;
@class CocoaVideoFilter;
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
@interface PreferencesWindowDelegate : NSObject <NSWindowDelegate>
#else
@interface PreferencesWindowDelegate : NSObject
#endif
{
NSObject *dummyObject;
NSWindow *window;
NSWindow *firmwareConfigSheet;
NSObjectController *cdsCoreController;
NSObjectController *emuWindowController;
NSObjectController *prefWindowController;
NSObjectController *cheatWindowController;
NSArrayController *cheatDatabaseController;
NSView *viewGeneral;
InputPrefsView *viewInput;
NSView *viewDisplay;
NSView *viewSound;
NSView *viewEmulation;
NSPopUpButton *displayRotationMenu;
NSMenuItem *displayRotationMenuCustomItem;
NSTextField *displayRotationField;
NSImage *iconVolumeFull;
NSImage *iconVolumeTwoThird;
NSImage *iconVolumeOneThird;
NSImage *iconVolumeMute;
NSPopUpButton *spuSyncMethodMenu;
NSImageView *previewImageView;
CocoaVideoFilter *videoFilter;
CocoaVideoFilter *bilinearVideoFilter;
NSMutableDictionary *bindings;
}
@property (readonly) IBOutlet NSObject *dummyObject;
@property (readonly) IBOutlet NSWindow *window;
@property (readonly) IBOutlet NSWindow *firmwareConfigSheet;
@property (readonly) IBOutlet NSObjectController *cdsCoreController;
@property (readonly) IBOutlet NSObjectController *emuWindowController;
@property (readonly) IBOutlet NSObjectController *prefWindowController;
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
@property (readonly) IBOutlet NSView *viewGeneral;
@property (readonly) IBOutlet InputPrefsView *viewInput;
@property (readonly) IBOutlet NSView *viewDisplay;
@property (readonly) IBOutlet NSView *viewSound;
@property (readonly) IBOutlet NSView *viewEmulation;
@property (readonly) IBOutlet NSPopUpButton *displayRotationMenu;
@property (readonly) IBOutlet NSMenuItem *displayRotationMenuCustomItem;
@property (readonly) IBOutlet NSTextField *displayRotationField;
@property (readonly) IBOutlet NSPopUpButton *spuSyncMethodMenu;
@property (readonly) IBOutlet NSImageView *previewImageView;
@property (assign) NSMutableDictionary *bindings;
- (IBAction) showGeneralView:(id)sender;
- (IBAction) showInputView:(id)sender;
- (IBAction) showDisplayView:(id)sender;
- (IBAction) showSoundView:(id)sender;
- (IBAction) showEmulationView:(id)sender;
- (IBAction) selectAutoloadRomOption:(id)sender;
- (IBAction) chooseAdvansceneDatabase:(id)sender;
- (void) chooseAdvansceneDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (IBAction) chooseRomForAutoload:(id)sender;
- (void) chooseRomForAutoloadDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (IBAction) chooseCheatDatabase:(id)sender;
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (IBAction) selectSoundInputMode:(id)sender;
- (IBAction) selectDisplayMode:(id)sender;
- (IBAction) selectDisplaySize:(id)sender;
- (IBAction) selectDisplayRotation:(id)sender;
- (void) updateDisplayRotationMenu:(double)displayRotation;
- (IBAction) setUseBilinear:(id)sender;
- (IBAction) selectVideoFilterType:(id)sender;
- (IBAction) updateVolumeIcon:(id)sender;
- (IBAction) selectSPUSyncMode:(id)sender;
- (IBAction) selectSPUSyncMethod:(id)sender;
- (IBAction) chooseARM9BiosImage:(id)sender;
- (IBAction) chooseARM7BiosImage:(id)sender;
- (IBAction) chooseFirmwareImage:(id)sender;
- (void) chooseArm9BiosImageDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (void) chooseArm7BiosImageDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (void) chooseFirmwareImageDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (IBAction) configureInternalFirmware:(id)sender;
- (IBAction) closeFirmwareConfigSheet:(id)sender;
- (void) didEndFirmwareConfigSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
- (void) switchContentView:(NSView *)theView;
@end

View File

@ -0,0 +1,824 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#import "preferencesWindowDelegate.h"
#import "displayView.h"
#import "cocoa_core.h"
#import "cocoa_cheat.h"
#import "cocoa_globals.h"
#import "cocoa_input.h"
#import "cocoa_file.h"
#import "cocoa_mic.h"
#import "cocoa_videofilter.h"
#import "cocoa_util.h"
@implementation PreferencesWindowDelegate
@synthesize dummyObject;
@synthesize window;
@synthesize firmwareConfigSheet;
@synthesize cdsCoreController;
@synthesize emuWindowController;
@synthesize prefWindowController;
@synthesize cheatWindowController;
@synthesize cheatDatabaseController;
@synthesize viewGeneral;
@synthesize viewInput;
@synthesize viewDisplay;
@synthesize viewSound;
@synthesize viewEmulation;
@synthesize displayRotationMenu;
@synthesize displayRotationMenuCustomItem;
@synthesize displayRotationField;
@synthesize spuSyncMethodMenu;
@synthesize previewImageView;
@synthesize bindings;
- (id)init
{
self = [super init];
if(self == nil)
{
return nil;
}
bindings = [[NSMutableDictionary alloc] init];
if (bindings == nil)
{
[self release];
self = nil;
return self;
}
VideoFilterTypeID vfType = (VideoFilterTypeID)[[NSUserDefaults standardUserDefaults] integerForKey:@"DisplayView_VideoFilter"];
NSImage *videoFilterImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"VideoFilterPreview_64x64" ofType:@"png"]];
videoFilter = [[CocoaVideoFilter alloc] initWithSize:[videoFilterImage size] typeID:vfType];
NSSize vfDestSize = [videoFilter destSize];
NSUInteger vfWidth = (NSUInteger)vfDestSize.width;
NSUInteger vfHeight = (NSUInteger)vfDestSize.height;
NSArray *imageRepArray = [videoFilterImage representations];
const NSBitmapImageRep *imageRep = [imageRepArray objectAtIndex:0];
RGB888ToRGBA8888Buffer((const uint32_t *)[imageRep bitmapData], (uint32_t *)[videoFilter srcBufferPtr], (64 * 64));
[videoFilterImage release];
BOOL useBilinear = [[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_UseBilinearOutput"];
if (vfWidth <= 64 || vfHeight <= 64)
{
[videoFilter changeFilter:VideoFilterTypeID_Nearest2X];
vfDestSize = [videoFilter destSize];
vfWidth = (NSUInteger)vfDestSize.width;
vfHeight = (NSUInteger)vfDestSize.height;
if (useBilinear)
{
bilinearVideoFilter = [[CocoaVideoFilter alloc] initWithSize:vfDestSize typeID:VideoFilterTypeID_Bilinear];
}
else
{
bilinearVideoFilter = [[CocoaVideoFilter alloc] initWithSize:vfDestSize typeID:VideoFilterTypeID_Nearest2X];
}
}
else if (vfWidth >= 256 || vfHeight >= 256)
{
bilinearVideoFilter = [[CocoaVideoFilter alloc] initWithSize:vfDestSize typeID:VideoFilterTypeID_None];
}
else
{
if (useBilinear)
{
bilinearVideoFilter = [[CocoaVideoFilter alloc] initWithSize:vfDestSize typeID:VideoFilterTypeID_Bilinear];
}
else
{
bilinearVideoFilter = [[CocoaVideoFilter alloc] initWithSize:vfDestSize typeID:VideoFilterTypeID_Nearest2X];
}
}
RGB888ToRGBA8888Buffer((const uint32_t *)[videoFilter runFilter], (uint32_t *)[bilinearVideoFilter srcBufferPtr], (vfWidth * vfHeight));
[bindings setObject:[bilinearVideoFilter image] forKey:@"VideoFilterPreviewImage"];
iconVolumeFull = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Icon_VolumeFull_16x16" ofType:@"png"]];
iconVolumeTwoThird = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Icon_VolumeTwoThird_16x16" ofType:@"png"]];
iconVolumeOneThird = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Icon_VolumeOneThird_16x16" ofType:@"png"]];
iconVolumeMute = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Icon_VolumeMute_16x16" ofType:@"png"]];
[bindings setObject:iconVolumeFull forKey:@"volumeIconImage"];
return self;
}
- (void)dealloc
{
[iconVolumeFull release];
[iconVolumeTwoThird release];
[iconVolumeOneThird release];
[iconVolumeMute release];
[bindings release];
[videoFilter release];
[super dealloc];
}
- (IBAction) showGeneralView:(id)sender
{
[self switchContentView:viewGeneral];
}
- (IBAction) showInputView:(id)sender
{
[self switchContentView:(NSView *)viewInput];
[window makeFirstResponder:(NSView *)viewInput];
}
- (IBAction) showDisplayView:(id)sender
{
[self switchContentView:viewDisplay];
}
- (IBAction) showSoundView:(id)sender
{
[self switchContentView:viewSound];
}
- (IBAction) showEmulationView:(id)sender
{
[self switchContentView:viewEmulation];
}
- (IBAction) selectAutoloadRomOption:(id)sender
{
NSInteger option = [(NSMenuItem *)sender tag];
[[NSUserDefaults standardUserDefaults] setInteger:option forKey:@"General_AutoloadROMOption"];
if (option == 1)
{
NSString *autoloadRomPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"General_AutoloadROMSelectedPath"];
if ([autoloadRomPath length] == 0)
{
[self chooseRomForAutoload:sender];
}
}
}
- (IBAction) chooseRomForAutoload:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_SELECT_ROM_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_ROM_DS, @FILE_EXT_ROM_GBA, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:window
completionHandler:^(NSInteger result) {
[self chooseRomForAutoloadDidEnd:panel returnCode:result contextInfo:nil];
} ];
#else
[panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(chooseRomForAutoloadDidEnd:returnCode:contextInfo:)
contextInfo:nil];
#endif
}
- (void) chooseRomForAutoloadDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == NSCancelButton)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
if(selectedFileURL == nil)
{
return;
}
NSString *selectedFile = [selectedFileURL path];
[[NSUserDefaults standardUserDefaults] setObject:selectedFile forKey:@"General_AutoloadROMSelectedPath"];
[bindings setValue:[selectedFile lastPathComponent] forKey:@"AutoloadRomName"];
}
- (IBAction) chooseAdvansceneDatabase:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_SELECT_ADVANSCENE_DB_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_ADVANSCENE_DB, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:window
completionHandler:^(NSInteger result) {
[self chooseAdvansceneDatabaseDidEnd:panel returnCode:result contextInfo:nil];
} ];
#else
[panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(chooseAdvansceneDatabaseDidEnd:returnCode:contextInfo:)
contextInfo:nil];
#endif
}
- (void) chooseAdvansceneDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == NSCancelButton)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
if(selectedFileURL == nil)
{
return;
}
NSString *selectedFile = [selectedFileURL path];
[[NSUserDefaults standardUserDefaults] setObject:selectedFile forKey:@"Advanscene_DatabasePath"];
[bindings setValue:[selectedFile lastPathComponent] forKey:@"AdvansceneDatabaseName"];
}
- (IBAction) chooseCheatDatabase:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_SELECT_R4_CHEAT_DB_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_R4_CHEAT_DB, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:window
completionHandler:^(NSInteger result) {
[self chooseCheatDatabaseDidEnd:panel returnCode:result contextInfo:nil];
} ];
#else
[panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(chooseCheatDatabaseDidEnd:returnCode:contextInfo:)
contextInfo:nil];
#endif
}
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == NSCancelButton)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
if(selectedFileURL == nil)
{
return;
}
NSString *selectedFile = [selectedFileURL path];
[[NSUserDefaults standardUserDefaults] setObject:selectedFile forKey:@"R4Cheat_DatabasePath"];
[bindings setValue:[selectedFile lastPathComponent] forKey:@"R4CheatDatabaseName"];
BOOL isRomLoaded = [(NSNumber *)[(NSMutableDictionary *)[emuWindowController content] valueForKey:@"isRomLoaded"] boolValue];
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
CocoaDSCheatManager *cdsCheats = (CocoaDSCheatManager *)[cheatWindowBindings valueForKey:@"cheatList"];
if (isRomLoaded == YES && cdsCheats != nil)
{
NSInteger error = 0;
NSMutableArray *dbList = [cdsCheats cheatListFromDatabase:selectedFileURL errorCode:&error];
if (dbList != nil)
{
[cheatDatabaseController setContent:dbList];
NSString *titleString = cdsCheats.dbTitle;
NSString *dateString = cdsCheats.dbDate;
[cheatWindowBindings setValue:titleString forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:dateString forKey:@"cheatDBDate"];
[cheatWindowBindings setValue:[NSString stringWithFormat:@"%d", [dbList count]] forKey:@"cheatDBItemCount"];
}
else
{
// TODO: Display an error message here.
[cheatWindowBindings setValue:@"---" forKey:@"cheatDBItemCount"];
switch (error)
{
case CHEATEXPORT_ERROR_FILE_NOT_FOUND:
NSLog(@"R4 Cheat Database read failed! Could not load the database file!");
[cheatWindowBindings setValue:@"Database not loaded." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"CANNOT LOAD FILE" forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_WRONG_FILE_FORMAT:
NSLog(@"R4 Cheat Database read failed! Wrong file format!");
[cheatWindowBindings setValue:@"Database load error." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"FAILED TO LOAD FILE" forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_SERIAL_NOT_FOUND:
NSLog(@"R4 Cheat Database read failed! Could not find the serial number for this game in the database!");
[cheatWindowBindings setValue:@"ROM not found in database." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"ROM not found." forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_EXPORT_FAILED:
NSLog(@"R4 Cheat Database read failed! Could not read the database file!");
[cheatWindowBindings setValue:@"Database read error." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"CANNOT READ FILE" forKey:@"cheatDBDate"];
break;
default:
break;
}
}
}
}
- (IBAction) selectSoundInputMode:(id)sender
{
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
if (cdsCore != nil)
{
[cdsCore.cdsController setSoundInputMode:[[NSUserDefaults standardUserDefaults] integerForKey:@"Input_AudioInputMode"]];
}
}
- (IBAction) selectDisplayMode:(id)sender
{
NSInteger displayMode = [(NSMenuItem *)sender tag];
[[NSUserDefaults standardUserDefaults] setInteger:displayMode forKey:@"DisplayView_Mode"];
}
- (IBAction) selectDisplaySize:(id)sender
{
NSInteger displaySize = [(NSMenuItem *)sender tag];
[[NSUserDefaults standardUserDefaults] setInteger:displaySize forKey:@"DisplayView_Size"];
}
- (IBAction) selectDisplayRotation:(id)sender
{
NSInteger displayRotation = [(NSMenuItem *)sender tag];
if (displayRotation != -1)
{
[[NSUserDefaults standardUserDefaults] setDouble:displayRotation forKey:@"DisplayView_Rotation"];
}
}
- (IBAction) setUseBilinear:(id)sender
{
BOOL useBilinear = [CocoaDSUtil getIBActionSenderButtonStateBool:sender];
NSUInteger previewSrcWidth = (NSUInteger)[bilinearVideoFilter srcSize].width;
NSUInteger previewSrcHeight = (NSUInteger)[bilinearVideoFilter srcSize].height;
if (previewSrcWidth <= 128 || previewSrcHeight <= 128)
{
if (useBilinear)
{
[bilinearVideoFilter changeFilter:VideoFilterTypeID_Bilinear];
}
else
{
[bilinearVideoFilter changeFilter:VideoFilterTypeID_Nearest2X];
}
}
NSBitmapImageRep *newPreviewImageRep = [bilinearVideoFilter bitmapImageRep];
NSImage *videoFilterPreviewImage = [bindings objectForKey:@"VideoFilterPreviewImage"];
NSArray *imageRepArray = [videoFilterPreviewImage representations];
NSImageRep *oldImageRep = [imageRepArray objectAtIndex:0];
[videoFilterPreviewImage removeRepresentation:oldImageRep];
[videoFilterPreviewImage addRepresentation:newPreviewImageRep];
[previewImageView setNeedsDisplay:YES];
}
- (IBAction) selectVideoFilterType:(id)sender
{
VideoFilterTypeID vfType = (VideoFilterTypeID)[CocoaDSUtil getIBActionSenderTag:sender];
BOOL useBilinear = [[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_UseBilinearOutput"];
[[NSUserDefaults standardUserDefaults] setInteger:vfType forKey:@"DisplayView_VideoFilter"];
[videoFilter changeFilter:vfType];
NSSize vfDestSize = [videoFilter destSize];
NSUInteger vfWidth = (NSUInteger)[videoFilter destSize].width;
NSUInteger vfHeight = (NSUInteger)[videoFilter destSize].height;
if (vfWidth <= 64 || vfHeight <= 64)
{
[videoFilter changeFilter:VideoFilterTypeID_Nearest2X];
vfDestSize = [videoFilter destSize];
vfWidth = (NSUInteger)vfDestSize.width;
vfHeight = (NSUInteger)vfDestSize.height;
[bilinearVideoFilter setSourceSize:vfDestSize];
if (useBilinear)
{
[bilinearVideoFilter changeFilter:VideoFilterTypeID_Bilinear];
}
else
{
[bilinearVideoFilter changeFilter:VideoFilterTypeID_Nearest2X];
}
}
else if (vfWidth >= 256 || vfHeight >= 256)
{
[bilinearVideoFilter setSourceSize:vfDestSize];
[bilinearVideoFilter changeFilter:VideoFilterTypeID_None];
}
else
{
[bilinearVideoFilter setSourceSize:vfDestSize];
if (useBilinear)
{
[bilinearVideoFilter changeFilter:VideoFilterTypeID_Bilinear];
}
else
{
[bilinearVideoFilter changeFilter:VideoFilterTypeID_Nearest2X];
}
}
RGB888ToRGBA8888Buffer((const uint32_t *)[videoFilter runFilter], (uint32_t *)[bilinearVideoFilter srcBufferPtr], (vfWidth * vfHeight));
NSBitmapImageRep *newPreviewImageRep = [bilinearVideoFilter bitmapImageRep];
NSImage *videoFilterPreviewImage = [bindings objectForKey:@"VideoFilterPreviewImage"];
NSArray *imageRepArray = [videoFilterPreviewImage representations];
NSImageRep *oldImageRep = [imageRepArray objectAtIndex:0];
[videoFilterPreviewImage removeRepresentation:oldImageRep];
[videoFilterPreviewImage addRepresentation:newPreviewImageRep];
[previewImageView setNeedsDisplay:YES];
}
- (IBAction) updateVolumeIcon:(id)sender
{
NSImage *iconImage = (NSImage *)[bindings objectForKey:@"volumeIconImage"];
float vol = [[NSUserDefaults standardUserDefaults] floatForKey:@"Sound_Volume"];
if (vol <= 0.0f)
{
if (iconImage == iconVolumeMute)
{
return;
}
iconImage = iconVolumeMute;
}
else if (vol > 0.0f && vol <= VOLUME_THRESHOLD_LOW)
{
if (iconImage == iconVolumeOneThird)
{
return;
}
iconImage = iconVolumeOneThird;
}
else if (vol > VOLUME_THRESHOLD_LOW && vol <= VOLUME_THRESHOLD_HIGH)
{
if (iconImage == iconVolumeTwoThird)
{
return;
}
iconImage = iconVolumeTwoThird;
}
else
{
if (iconImage == iconVolumeFull)
{
return;
}
iconImage = iconVolumeFull;
}
[bindings setObject:iconImage forKey:@"volumeIconImage"];
}
- (IBAction) selectSPUSyncMode:(id)sender
{
NSInteger spuSyncMode = [[NSUserDefaults standardUserDefaults] integerForKey:@"SPU_SyncMode"];
if (spuSyncMode == SPU_SYNC_MODE_DUAL_SYNC_ASYNC)
{
[spuSyncMethodMenu setEnabled:NO];
}
else
{
[spuSyncMethodMenu setEnabled:YES];
}
}
- (IBAction) selectSPUSyncMethod:(id)sender
{
NSInteger spuSyncMethod = [(NSMenuItem *)sender tag];
[[NSUserDefaults standardUserDefaults] setInteger:spuSyncMethod forKey:@"SPU_SyncMethod"];
}
- (void) updateDisplayRotationMenu:(double)displayRotation
{
if (displayRotation == 0.0f ||
displayRotation == 90.0f ||
displayRotation == 180.0f ||
displayRotation == 270.0f)
{
[displayRotationMenu selectItemWithTag:(NSInteger)displayRotation];
}
else if (displayRotation < 0.0f || displayRotation >= 360.0f)
{
displayRotation = 0.0f;
[displayRotationField setFloatValue:displayRotation];
[displayRotationMenu selectItemWithTag:(NSInteger)displayRotation];
}
else
{
[displayRotationMenu selectItem:displayRotationMenuCustomItem];
}
}
- (IBAction) chooseARM9BiosImage:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_SELECT_ARM9_IMAGE_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_HW_IMAGE_FILE, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:window
completionHandler:^(NSInteger result) {
[self chooseArm9BiosImageDidEnd:panel returnCode:result contextInfo:nil];
} ];
#else
[panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(chooseArm9BiosImageDidEnd:returnCode:contextInfo:)
contextInfo:nil];
#endif
}
- (IBAction) chooseARM7BiosImage:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_SELECT_ARM7_IMAGE_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_HW_IMAGE_FILE, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:window
completionHandler:^(NSInteger result) {
[self chooseArm7BiosImageDidEnd:panel returnCode:result contextInfo:nil];
} ];
#else
[panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(chooseArm7BiosImageDidEnd:returnCode:contextInfo:)
contextInfo:nil];
#endif
}
- (IBAction) chooseFirmwareImage:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_SELECT_FIRMWARE_IMAGE_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_HW_IMAGE_FILE, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:window
completionHandler:^(NSInteger result) {
[self chooseFirmwareImageDidEnd:panel returnCode:result contextInfo:nil];
} ];
#else
[panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(chooseFirmwareImageDidEnd:returnCode:contextInfo:)
contextInfo:nil];
#endif
}
- (void) chooseArm9BiosImageDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == NSCancelButton)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
if(selectedFileURL == nil)
{
return;
}
NSString *selectedFile = [selectedFileURL path];
[[NSUserDefaults standardUserDefaults] setObject:selectedFile forKey:@"BIOS_ARM9ImagePath"];
[bindings setValue:[selectedFile lastPathComponent] forKey:@"Arm9BiosImageName"];
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
if (cdsCore != nil)
{
[cdsCore setArm9ImageURL:selectedFileURL];
}
}
- (void) chooseArm7BiosImageDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == NSCancelButton)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
if(selectedFileURL == nil)
{
return;
}
NSString *selectedFile = [selectedFileURL path];
[[NSUserDefaults standardUserDefaults] setObject:selectedFile forKey:@"BIOS_ARM7ImagePath"];
[bindings setValue:[selectedFile lastPathComponent] forKey:@"Arm7BiosImageName"];
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
if (cdsCore != nil)
{
[cdsCore setArm7ImageURL:selectedFileURL];
}
}
- (void) chooseFirmwareImageDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == NSCancelButton)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
if(selectedFileURL == nil)
{
return;
}
NSString *selectedFile = [selectedFileURL path];
[[NSUserDefaults standardUserDefaults] setObject:selectedFile forKey:@"Emulation_FirmwareImagePath"];
[bindings setValue:[selectedFile lastPathComponent] forKey:@"FirmwareImageName"];
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
if (cdsCore != nil)
{
[cdsCore setFirmwareImageURL:selectedFileURL];
}
}
- (IBAction) configureInternalFirmware:(id)sender
{
[NSApp beginSheet:firmwareConfigSheet
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(didEndFirmwareConfigSheet:returnCode:contextInfo:)
contextInfo:nil];
}
- (IBAction) closeFirmwareConfigSheet:(id)sender
{
NSWindow *sheet = [(NSControl *)sender window];
NSInteger code = [CocoaDSUtil getIBActionSenderTag:sender];
// Force end of editing of any text fields.
[sheet makeFirstResponder:nil];
[NSApp endSheet:sheet returnCode:code];
}
- (void) didEndFirmwareConfigSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
}
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
{
[self updateDisplayRotationMenu:[displayRotationField floatValue]];
}
- (void) switchContentView:(NSView *)theView
{
if ([window contentView] == theView)
{
return;
}
NSRect newFrame = [window frameRectForContentRect:[theView frame]];
newFrame.origin.x = [window frame].origin.x;
newFrame.origin.y = [window frame].origin.y + [[window contentView] frame].size.height - [theView frame].size.height;
[[window contentView] retain];
NSView *tempView = [[NSView alloc] initWithFrame:[[window contentView] frame]];
[window setContentView:tempView];
[window setFrame:newFrame display:YES animate:YES];
[window setContentView:theView];
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
[prefWindowController setContent:self.bindings];
}
@end

View File

@ -0,0 +1,608 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "videofilter.h"
// Parameters for Scanline filter
int scanline_filter_a = 2;
int scanline_filter_b = 4;
/********************************************************************************************
CLASS CONSTRUCTORS
********************************************************************************************/
VideoFilter::VideoFilter()
{
SSurface *newSrcSurface = (SSurface *)malloc(sizeof(SSurface));
if (newSrcSurface == NULL)
{
throw;
}
SSurface *newDestSurface = (SSurface *)malloc(sizeof(SSurface));
if (newDestSurface == NULL)
{
free(newSrcSurface);
newSrcSurface = NULL;
throw;
}
pthread_mutex_init(&_mutexSrc, NULL);
pthread_mutex_init(&_mutexDest, NULL);
pthread_mutex_init(&_mutexTypeID, NULL);
pthread_mutex_init(&_mutexTypeString, NULL);
pthread_cond_init(&_condRunning, NULL);
_isFilterRunning = false;
_srcSurfaceBufferMaster = NULL;
newSrcSurface->Surface = NULL;
newDestSurface->Surface = NULL;
_srcSurface = newSrcSurface;
_destSurface = newDestSurface;
_typeID = VideoFilterTypeID_None;
SetSourceSize(1, 1);
}
VideoFilter::VideoFilter(unsigned int srcWidth, unsigned int srcHeight)
{
SSurface *newSrcSurface = (SSurface *)malloc(sizeof(SSurface));
if (newSrcSurface == NULL)
{
throw;
}
SSurface *newDestSurface = (SSurface *)malloc(sizeof(SSurface));
if (newDestSurface == NULL)
{
free(newSrcSurface);
newSrcSurface = NULL;
throw;
}
pthread_mutex_init(&_mutexSrc, NULL);
pthread_mutex_init(&_mutexDest, NULL);
pthread_mutex_init(&_mutexTypeID, NULL);
pthread_mutex_init(&_mutexTypeString, NULL);
pthread_cond_init(&_condRunning, NULL);
_isFilterRunning = false;
_srcSurfaceBufferMaster = NULL;
newSrcSurface->Surface = NULL;
newDestSurface->Surface = NULL;
_srcSurface = newSrcSurface;
_destSurface = newDestSurface;
_typeID = VideoFilterTypeID_None;
SetSourceSize(srcWidth, srcHeight);
}
VideoFilter::VideoFilter(unsigned int srcWidth, unsigned int srcHeight, VideoFilterTypeID typeID)
{
SSurface *newSrcSurface = (SSurface *)malloc(sizeof(SSurface));
if (newSrcSurface == NULL)
{
throw;
}
SSurface *newDestSurface = (SSurface *)malloc(sizeof(SSurface));
if (newDestSurface == NULL)
{
free(newSrcSurface);
newSrcSurface = NULL;
throw;
}
pthread_mutex_init(&_mutexSrc, NULL);
pthread_mutex_init(&_mutexDest, NULL);
pthread_mutex_init(&_mutexTypeID, NULL);
pthread_mutex_init(&_mutexTypeString, NULL);
pthread_cond_init(&_condRunning, NULL);
_isFilterRunning = false;
_srcSurfaceBufferMaster = NULL;
newSrcSurface->Surface = NULL;
newDestSurface->Surface = NULL;
_srcSurface = newSrcSurface;
_destSurface = newDestSurface;
_typeID = typeID;
SetSourceSize(srcWidth, srcHeight);
}
/********************************************************************************************
CLASS DESTRUCTOR
********************************************************************************************/
VideoFilter::~VideoFilter()
{
pthread_mutex_lock(&this->_mutexDest);
while (this->_isFilterRunning)
{
pthread_cond_wait(&this->_condRunning, &this->_mutexDest);
}
free(_destSurface->Surface);
_destSurface->Surface = NULL;
free(_destSurface);
_destSurface = NULL;
pthread_mutex_unlock(&_mutexDest);
pthread_mutex_lock(&_mutexSrc);
free(_srcSurfaceBufferMaster);
_srcSurfaceBufferMaster = NULL;
_srcSurface->Surface = NULL;
free(_srcSurface);
_srcSurface = NULL;
pthread_mutex_unlock(&_mutexSrc);
pthread_mutex_destroy(&_mutexSrc);
pthread_mutex_destroy(&_mutexDest);
pthread_mutex_destroy(&_mutexTypeID);
pthread_mutex_destroy(&_mutexTypeString);
pthread_cond_destroy(&_condRunning);
}
/********************************************************************************************
SetSourceSize()
Sets the rectangular size of the source image. This method reallocates memory based
on the input size, and therefore returns a bool value upon success or failure of
resizing.
Takes:
width - The width of the source image in pixels.
height - The height of the source image in pixels.
Returns:
A bool that reports if the resizing was successful. A value of true means success,
while a value of false means failure.
********************************************************************************************/
bool VideoFilter::SetSourceSize(unsigned int width, unsigned int height)
{
bool result = false;
pthread_mutex_lock(&this->_mutexSrc);
// Overallocate the source buffer by 8 rows of pixels to account for out-of-bounds
// memory reads done by some filters.
uint32_t *newSurfaceBuffer = (uint32_t *)calloc(width * (height + 8), sizeof(uint32_t));
if (newSurfaceBuffer == NULL)
{
return result;
}
this->_srcSurface->Width = width;
this->_srcSurface->Height = height;
this->_srcSurface->Pitch = width * 2;
// Set the working source buffer pointer so that the working memory block is padded
// with 4 pixel rows worth of memory on both sides.
this->_srcSurface->Surface = (unsigned char *)(newSurfaceBuffer + (width * 4));
free(this->_srcSurfaceBufferMaster);
this->_srcSurfaceBufferMaster = newSurfaceBuffer;
pthread_mutex_unlock(&this->_mutexSrc);
result = this->ChangeFilter(this->GetTypeID());
return result;
}
/********************************************************************************************
ChangeFilter()
Changes the video filter type.
Takes:
typeID - The type ID of the video filter. See the VideoFilterTypeID
enumeration for possible values.
Returns:
A bool that reports if the filter change was successful. A value of true means
success, while a value of false means failure.
********************************************************************************************/
bool VideoFilter::ChangeFilter(VideoFilterTypeID typeID)
{
bool result = false;
pthread_mutex_lock(&this->_mutexSrc);
const unsigned int srcWidth = this->_srcSurface->Width;
const unsigned int srcHeight = this->_srcSurface->Height;
pthread_mutex_unlock(&this->_mutexSrc);
unsigned int destWidth = srcWidth;
unsigned int destHeight = srcHeight;
const char *typeString = VideoFilter::GetTypeStringByID(typeID);
VideoFilterCallback filterCallback = NULL;
switch (typeID)
{
case VideoFilterTypeID_None:
break;
case VideoFilterTypeID_LQ2X:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderLQ2X;
break;
case VideoFilterTypeID_LQ2XS:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderLQ2XS;
break;
case VideoFilterTypeID_HQ2X:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderHQ2X;
break;
case VideoFilterTypeID_HQ2XS:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderHQ2XS;
break;
case VideoFilterTypeID_HQ4X:
destWidth = srcWidth * 4;
destHeight = srcHeight * 4;
filterCallback = &RenderHQ4X;
break;
case VideoFilterTypeID_2xSaI:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &Render2xSaI;
break;
case VideoFilterTypeID_Super2xSaI:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderSuper2xSaI;
break;
case VideoFilterTypeID_SuperEagle:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderSuperEagle;
break;
case VideoFilterTypeID_Scanline:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderScanline;
break;
case VideoFilterTypeID_Bilinear:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderBilinear;
break;
case VideoFilterTypeID_Nearest2X:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderNearest2X;
break;
case VideoFilterTypeID_Nearest1_5X:
destWidth = srcWidth * 3 / 2;
destHeight = srcHeight * 3 / 2;
filterCallback = &RenderNearest_1Point5x;
break;
case VideoFilterTypeID_NearestPlus1_5X:
destWidth = srcWidth * 3 / 2;
destHeight = srcHeight * 3 / 2;
filterCallback = &RenderNearestPlus_1Point5x;
break;
case VideoFilterTypeID_EPX:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderEPX;
break;
case VideoFilterTypeID_EPXPlus:
destWidth = srcWidth * 2;
destHeight = srcHeight * 2;
filterCallback = &RenderEPXPlus;
break;
case VideoFilterTypeID_EPX1_5X:
destWidth = srcWidth * 3 / 2;
destHeight = srcHeight * 3 / 2;
filterCallback = &RenderEPX_1Point5x;
break;
case VideoFilterTypeID_EPXPlus1_5X:
destWidth = srcWidth * 3 / 2;
destHeight = srcHeight * 3 / 2;
filterCallback = &RenderEPXPlus_1Point5x;
break;
default:
break;
}
pthread_mutex_lock(&this->_mutexDest);
uint32_t *newSurfaceBuffer = (uint32_t *)calloc(destWidth * destHeight, sizeof(uint32_t));
if (newSurfaceBuffer == NULL)
{
return result;
}
this->_filterCallback = filterCallback;
this->_destSurface->Width = destWidth;
this->_destSurface->Height = destHeight;
this->_destSurface->Pitch = destWidth * 2;
free(this->_destSurface->Surface);
this->_destSurface->Surface = (unsigned char*)newSurfaceBuffer;
pthread_mutex_unlock(&this->_mutexDest);
this->SetTypeID(typeID);
this->SetTypeString(typeString);
result = true;
return result;
}
/********************************************************************************************
RunFilter()
Runs the pixels in the source buffer through the video filter, and then stores
the resulting pixels into the destination buffer.
Takes:
Nothing.
Returns:
A pointer to the destination buffer.
********************************************************************************************/
uint32_t* VideoFilter::RunFilter()
{
pthread_mutex_lock(&this->_mutexDest);
this->_isFilterRunning = true;
uint32_t *destBufPtr = (uint32_t *)this->_destSurface->Surface;
pthread_mutex_lock(&this->_mutexSrc);
if (this->_filterCallback == NULL)
{
memcpy(this->_destSurface->Surface, this->_srcSurface->Surface, this->_destSurface->Width * this->_destSurface->Height * sizeof(uint32_t));
}
else
{
this->_filterCallback(*this->_srcSurface, *this->_destSurface);
}
pthread_mutex_unlock(&this->_mutexSrc);
this->_isFilterRunning = false;
pthread_cond_signal(&this->_condRunning);
pthread_mutex_unlock(&this->_mutexDest);
return destBufPtr;
}
/********************************************************************************************
GetTypeStringByID() - STATIC
Returns a C-string representation of the passed in video filter type.
Takes:
typeID - The type ID of the video filter. See the VideoFilterTypeID
enumeration for possible values.
Returns:
A C-string that represents the video filter type. If typeID is invalid,
this method returns the string "Unknown".
********************************************************************************************/
const char* VideoFilter::GetTypeStringByID(VideoFilterTypeID typeID)
{
const char *typeString = "Unknown";
switch (typeID)
{
case VideoFilterTypeID_None:
typeString = VIDEOFILTERTYPE_NONE_STRING;
break;
case VideoFilterTypeID_LQ2X:
typeString = VIDEOFILTERTYPE_LQ2X_STRING;
break;
case VideoFilterTypeID_LQ2XS:
typeString = VIDEOFILTERTYPE_LQ2XS_STRING;
break;
case VideoFilterTypeID_HQ2X:
typeString = VIDEOFILTERTYPE_HQ2X_STRING;
break;
case VideoFilterTypeID_HQ2XS:
typeString = VIDEOFILTERTYPE_HQ2XS_STRING;
break;
case VideoFilterTypeID_HQ4X:
typeString = VIDEOFILTERTYPE_HQ4X_STRING;
break;
case VideoFilterTypeID_2xSaI:
typeString = VIDEOFILTERTYPE_2XSAI_STRING;
break;
case VideoFilterTypeID_Super2xSaI:
typeString = VIDEOFILTERTYPE_SUPER_2XSAI_STRING;
break;
case VideoFilterTypeID_SuperEagle:
typeString = VIDEOFILTERTYPE_SUPER_EAGLE_STRING;
break;
case VideoFilterTypeID_Scanline:
typeString = VIDEOFILTERTYPE_SCANLINE_STRING;
break;
case VideoFilterTypeID_Bilinear:
typeString = VIDEOFILTERTYPE_BILINEAR_STRING;
break;
case VideoFilterTypeID_Nearest2X:
typeString = VIDEOFILTERTYPE_NEAREST_2X_STRING;
break;
case VideoFilterTypeID_Nearest1_5X:
typeString = VIDEOFILTERTYPE_NEAREST_1_5X_STRING;
break;
case VideoFilterTypeID_NearestPlus1_5X:
typeString = VIDEOFILTERTYPE_NEAREST_PLUS_1_5X_STRING;
break;
case VideoFilterTypeID_EPX:
typeString = VIDEOFILTERTYPE_EPX_STRING;
break;
case VideoFilterTypeID_EPXPlus:
typeString = VIDEOFILTERTYPE_EPX_PLUS_STRING;
break;
case VideoFilterTypeID_EPX1_5X:
typeString = VIDEOFILTERTYPE_EPX_1_5X_STRING;
break;
case VideoFilterTypeID_EPXPlus1_5X:
typeString = VIDEOFILTERTYPE_EPX_PLUS_1_5X_STRING;
break;
default:
break;
}
return typeString;
}
/********************************************************************************************
ACCESSORS
********************************************************************************************/
VideoFilterTypeID VideoFilter::GetTypeID()
{
pthread_mutex_lock(&this->_mutexTypeID);
VideoFilterTypeID typeID = this->_typeID;
pthread_mutex_unlock(&this->_mutexTypeID);
return typeID;
}
void VideoFilter::SetTypeID(VideoFilterTypeID typeID)
{
pthread_mutex_lock(&this->_mutexTypeID);
this->_typeID = typeID;
pthread_mutex_unlock(&this->_mutexTypeID);
}
const char* VideoFilter::GetTypeString()
{
pthread_mutex_lock(&this->_mutexTypeString);
const char *typeString = this->_typeString.c_str();
pthread_mutex_unlock(&this->_mutexTypeString);
return typeString;
}
void VideoFilter::SetTypeString(const char *typeString)
{
pthread_mutex_lock(&this->_mutexTypeString);
this->_typeString = typeString;
pthread_mutex_unlock(&this->_mutexTypeString);
}
void VideoFilter::SetTypeString(std::string typeString)
{
pthread_mutex_lock(&this->_mutexTypeString);
this->_typeString = typeString;
pthread_mutex_unlock(&this->_mutexTypeString);
}
uint32_t* VideoFilter::GetSrcBufferPtr()
{
pthread_mutex_lock(&this->_mutexSrc);
uint32_t *ptr = (uint32_t *)this->_srcSurface->Surface;
pthread_mutex_unlock(&this->_mutexSrc);
return ptr;
}
uint32_t* VideoFilter::GetDestBufferPtr()
{
pthread_mutex_lock(&this->_mutexDest);
uint32_t *ptr = (uint32_t *)this->_destSurface->Surface;
pthread_mutex_unlock(&this->_mutexDest);
return ptr;
}
unsigned int VideoFilter::GetSrcWidth()
{
pthread_mutex_lock(&this->_mutexSrc);
unsigned int width = this->_srcSurface->Width;
pthread_mutex_unlock(&this->_mutexSrc);
return width;
}
unsigned int VideoFilter::GetSrcHeight()
{
pthread_mutex_lock(&this->_mutexSrc);
unsigned int height = this->_srcSurface->Height;
pthread_mutex_unlock(&this->_mutexSrc);
return height;
}
unsigned int VideoFilter::GetDestWidth()
{
pthread_mutex_lock(&this->_mutexDest);
unsigned int width = this->_destSurface->Width;
pthread_mutex_unlock(&this->_mutexDest);
return width;
}
unsigned int VideoFilter::GetDestHeight()
{
pthread_mutex_lock(&this->_mutexDest);
unsigned int height = this->_destSurface->Height;
pthread_mutex_unlock(&this->_mutexDest);
return height;
}

View File

@ -0,0 +1,139 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _VIDEOFILTER_
#define _VIDEOFILTER_
#include <stdlib.h>
#include <string>
#include <pthread.h>
#include "types.h"
#include "../windows/filter/filter.h"
// VIDEO FILTER TYPES
enum VideoFilterTypeID
{
VideoFilterTypeID_None = 0,
VideoFilterTypeID_LQ2X,
VideoFilterTypeID_LQ2XS,
VideoFilterTypeID_HQ2X,
VideoFilterTypeID_HQ2XS,
VideoFilterTypeID_HQ4X,
VideoFilterTypeID_2xSaI,
VideoFilterTypeID_Super2xSaI,
VideoFilterTypeID_SuperEagle,
VideoFilterTypeID_Scanline,
VideoFilterTypeID_Bilinear,
VideoFilterTypeID_Nearest2X,
VideoFilterTypeID_Nearest1_5X,
VideoFilterTypeID_NearestPlus1_5X,
VideoFilterTypeID_EPX,
VideoFilterTypeID_EPXPlus,
VideoFilterTypeID_EPX1_5X,
VideoFilterTypeID_EPXPlus1_5X
};
// VIDEO FILTER TYPE STRINGS
#define VIDEOFILTERTYPE_NONE_STRING "None"
#define VIDEOFILTERTYPE_LQ2X_STRING "LQ2X"
#define VIDEOFILTERTYPE_LQ2XS_STRING "LQ2XS"
#define VIDEOFILTERTYPE_HQ2X_STRING "HQ2X"
#define VIDEOFILTERTYPE_HQ2XS_STRING "HQ2XS"
#define VIDEOFILTERTYPE_HQ4X_STRING "HQ4X"
#define VIDEOFILTERTYPE_2XSAI_STRING "2xSaI"
#define VIDEOFILTERTYPE_SUPER_2XSAI_STRING "Super 2xSaI"
#define VIDEOFILTERTYPE_SUPER_EAGLE_STRING "Super Eagle"
#define VIDEOFILTERTYPE_SCANLINE_STRING "Scanline"
#define VIDEOFILTERTYPE_BILINEAR_STRING "Bilinear"
#define VIDEOFILTERTYPE_NEAREST_2X_STRING "Nearest 2x"
#define VIDEOFILTERTYPE_NEAREST_1_5X_STRING "Nearest 1.5x"
#define VIDEOFILTERTYPE_NEAREST_PLUS_1_5X_STRING "Nearest+ 1.5x"
#define VIDEOFILTERTYPE_EPX_STRING "EPX"
#define VIDEOFILTERTYPE_EPX_PLUS_STRING "EPX+"
#define VIDEOFILTERTYPE_EPX_1_5X_STRING "EPX 1.5x"
#define VIDEOFILTERTYPE_EPX_PLUS_1_5X_STRING "EPX+ 1.5x"
#define VIDEOFILTERTYPE_UNKNOWN_STRING "Unknown"
typedef void (*VideoFilterCallback)(SSurface Src, SSurface Dst);
/********************************************************************************************
VideoFilter - C++ CLASS
This is a wrapper class for managing the video filter functions from filter.h.
The steps to using a video filter are as follows:
1. Instantiate this class.
2. Set the rectangular size of the source image in pixels. (Can be done during
instantiation.)
3. Set the video filter type. (Can be done during instantiation.)
4. Fill in the source buffer with pixels in RGBA8888 format. This class provides
the GetSrcBufferPtr() accessor for the source buffer pointer.
5. Call RunFilter(). This runs the source buffer pixels through the chosen filter,
and then stores the resulting pixels into the destination buffer in RGBA8888
format.
6. At this point, the destination buffer pixels can be used. RunFilter() returns
a pointer to the destination buffer. Alternatively, GetDestBufferPtr() can be
used to get the pointer.
Thread Safety:
All methods are thread-safe.
********************************************************************************************/
class VideoFilter
{
private:
VideoFilterTypeID _typeID;
std::string _typeString;
SSurface *_srcSurface;
SSurface *_destSurface;
uint32_t *_srcSurfaceBufferMaster;
VideoFilterCallback _filterCallback;
bool _isFilterRunning;
pthread_mutex_t _mutexSrc;
pthread_mutex_t _mutexDest;
pthread_mutex_t _mutexTypeID;
pthread_mutex_t _mutexTypeString;
pthread_cond_t _condRunning;
void SetTypeID(VideoFilterTypeID typeID);
void SetTypeString(const char *typeString);
void SetTypeString(std::string typeString);
public:
VideoFilter();
VideoFilter(unsigned int srcWidth, unsigned int srcHeight);
VideoFilter(unsigned int srcWidth, unsigned int srcHeight, VideoFilterTypeID typeID);
~VideoFilter();
bool SetSourceSize(unsigned int width, unsigned int height);
bool ChangeFilter(VideoFilterTypeID typeID);
uint32_t* RunFilter();
static const char* GetTypeStringByID(VideoFilterTypeID typeID);
VideoFilterTypeID GetTypeID();
const char* GetTypeString();
uint32_t* GetSrcBufferPtr();
uint32_t* GetDestBufferPtr();
unsigned int GetSrcWidth();
unsigned int GetSrcHeight();
unsigned int GetDestWidth();
unsigned int GetDestHeight();
};
#endif