Compare commits

...

378 Commits

Author SHA1 Message Date
Kelvin Sherlock
60586a9e1b add gui option to completely disable the log window. 2024-05-25 15:01:34 -04:00
Kelvin Sherlock
fb7b2f3973 add gui option to completely disable the log window. 2024-05-25 15:00:27 -04:00
Kelvin Sherlock
4a6ba96803 version bump 2024-05-24 23:14:42 -04:00
Kelvin Sherlock
73ab4e0e41 updated plists for 0.265 2024-04-25 16:03:20 -04:00
Kelvin Sherlock
828c938e52 add bios support for for slot devices 2024-04-01 09:35:14 -04:00
Kelvin Sherlock
d1a2dcba21 updated mkmachines.py --extra 2024-03-30 19:10:14 -04:00
Kelvin Sherlock
5de27856ed add a couple more coco machines 2024-03-30 09:23:13 -04:00
Kelvin Sherlock
8da2ff4a20 for media beyond the second level, include default options since there isn't a UI to change it yet. 2024-03-28 19:28:32 -04:00
Kelvin Sherlock
e89536c932 version bump, add host.fst.po, move mame-data.tgz to the shared support directory. 2024-03-27 21:16:06 -04:00
Kelvin Sherlock
d2b592c7e5 0.264 update 2024-03-26 22:14:22 -04:00
Kelvin Sherlock
0afa433151 typo was preventing floppy mask calculation on systems with only 3.5" floppies. (#28) 2024-03-21 20:17:47 -04:00
Kelvin Sherlock
c2323ac998 rom manager - double-click to download. 2024-03-18 16:47:29 -04:00
Kelvin Sherlock
45fe32893f download controller - delete existing file (if it exists) when re-downloading an existing rom. 2024-03-18 16:39:42 -04:00
Kelvin Sherlock
308b15277c add 4x window option, aspect ratio for oric square pixels. 2024-03-18 15:25:34 -04:00
Kelvin Sherlock
bdd9df44ed add 3" floppy disk (pretend it's 3.5" for now). 2024-03-18 15:24:59 -04:00
Kelvin Sherlock
c58ff589dd Add oric. 2024-03-18 13:17:53 -04:00
Kelvin Sherlock
e3985856f3 Ample Extra updated machine definitions. 2024-03-10 20:18:16 -04:00
Kelvin Sherlock
a28c42a2b6 mactv 2024-03-10 19:21:25 -04:00
Kelvin Sherlock
78bcc88694 updated machine definitions. 2024-03-10 19:08:21 -04:00
Kelvin Sherlock
7e1e2fb8c5 move around the tandy order a little bit. 2024-03-10 19:07:16 -04:00
Kelvin Sherlock
7e64d6720d dragon disk drives 2024-03-10 19:06:28 -04:00
Kelvin Sherlock
ef8a4412f8 trs 80 floppies 2024-03-10 18:54:03 -04:00
Kelvin Sherlock
68429262c0 add the coco cart 2024-03-10 18:16:09 -04:00
Kelvin Sherlock
c2baf07256 update project with trs files 2024-03-10 18:12:22 -04:00
Kelvin Sherlock
cac8c1c054 Add some vintage tandy computers. 2024-03-07 22:11:40 -05:00
Kelvin Sherlock
0718aa5944 update cheatsheet for .263 changes 2024-03-01 18:19:16 -05:00
Kelvin Sherlock
8b37b5e840 version bump 2024-02-29 21:05:25 -05:00
Kelvin Sherlock
565e1109ff remove roms that don't exist (probably because they're merged) 2024-02-29 18:22:32 -05:00
Kelvin Sherlock
b7149a0b0d python deprecated behavior. 2024-02-29 18:21:37 -05:00
Kelvin Sherlock
8283a3beec MAME 0.263 updated machine definitions. 2024-02-29 17:52:01 -05:00
Kelvin Sherlock
17945e68ba Title Case rom names 2024-02-05 17:46:52 -05:00
Kelvin Sherlock
49e3e397d2 version bump 2024-02-03 13:54:10 -05:00
Kelvin Sherlock
5efa2b2cbf minor vmnet helper update. 2024-02-03 13:40:25 -05:00
Kelvin Sherlock
c536b8edb5 clean up machine names to be Title Case 2024-02-02 21:08:37 -05:00
Kelvin Sherlock
a6747e4f57 add single-density 8" floppies 2024-02-02 21:06:35 -05:00
Kelvin Sherlock
7dbaf4e12d Add back floppy bitmask since floppy order depends on slot order. 2024-02-02 21:06:07 -05:00
Kelvin Sherlock
24e3b01803 fix 8" floppy logic (a2vistaa800) 2024-02-01 18:41:34 -05:00
Kelvin Sherlock
d6a3e1e347 0.262 updates 2024-02-01 18:34:50 -05:00
Kelvin Sherlock
0244fbcc0b bump version 2023-12-02 16:42:07 -05:00
Kelvin Sherlock
ee1da060a3 vmnet helper -- don't assume vmnet_start_interface succeeded. 2023-12-02 16:24:04 -05:00
Kelvin Sherlock
6ce2fbc2d8 Updates to enable more machines, currently only in Ample Lite. 2023-12-02 16:10:40 -05:00
Kelvin Sherlock
56b34a4099 version bump due to bad build 2023-11-04 21:30:09 -04:00
Kelvin Sherlock
9f7c49e3e0 install_name_tool fixes 2023-11-04 21:29:52 -04:00
Kelvin Sherlock
70fc811b0d version bump 2023-11-04 17:12:23 -04:00
Kelvin Sherlock
377e6bc04e install_name_tool -change_rpath is actually just -change. weird. 2023-11-04 13:54:42 -04:00
Kelvin Sherlock
6ef3911da7 use an enum to identify special slots types (ram, bios, floppy disk controller) 2023-11-04 13:51:44 -04:00
Kelvin Sherlock
9b3223478c Eliminate the hard-coded slot values and use the slot name + dictionary for saving between machines. 2023-11-02 22:16:03 -04:00
Kelvin Sherlock
2198467def MAME 0.260 updates 2023-11-02 18:00:37 -04:00
Kelvin Sherlock
63a60ed8b7 bump for 0.249 hotfix 2023-10-03 11:23:31 -04:00
Kelvin Sherlock
9005cfe0ec 0.259 update, add UI support for Mac PDS slot 2023-09-29 18:16:37 -04:00
Kelvin Sherlock
2e62b33fb1 version bump 2023-09-01 20:27:52 -04:00
Kelvin Sherlock
e04d441cc5 add new resources to the xcode project 2023-08-31 20:04:34 -04:00
Kelvin Sherlock
f116c9ff1f mame 0.258 updates 2023-08-31 18:40:25 -04:00
Kelvin Sherlock
92cf747d65 version bump 2023-07-30 19:39:32 -04:00
Kelvin Sherlock
743fa57a44 add mac quadra to xcode, re-organize the models. 2023-07-28 19:02:59 -04:00
Kelvin Sherlock
970cbd6cdc mame 257 update 2023-07-28 18:38:29 -04:00
Kelvin Sherlock
3ce9df6650 version bump 2023-06-28 16:06:32 -04:00
Kelvin Sherlock
d84c5d7be3 Update for MAME 0.256, add Apple II ROM custom rom support. 2023-06-28 14:59:15 -04:00
Kelvin Sherlock
79617329e8 version bump 2023-05-31 18:06:12 -04:00
Kelvin Sherlock
dc67db2ce6 fix Atari rom names 2023-05-31 17:23:04 -04:00
Kelvin Sherlock
9031b481ce support for atari disk images/extensions. 2023-05-30 18:44:33 -04:00
Kelvin Sherlock
f38ab3288d Apple3 - RS232 -> Modem 2023-05-29 17:58:12 -04:00
Kelvin Sherlock
0aea4006cc Atari ST support. 2023-05-29 17:57:52 -04:00
Kelvin Sherlock
06233137a9 Add Atari ST support. 2023-05-29 17:57:07 -04:00
Kelvin Sherlock
8bc7e26279 version bump (44/0.254) 2023-04-27 19:09:09 -04:00
Kelvin Sherlock
aea14d8dd4 bug - CDATA notes in the software list weren't handled correctly (not used for apple family) 2023-04-27 17:58:38 -04:00
Kelvin Sherlock
23946962ad bug - bookmarks didn't restore built-in floppy disk settings (such as disabling the 5.25" drives on a iigs) 2023-04-27 17:58:29 -04:00
Kelvin Sherlock
d0987932a8 version bump 2023-03-31 00:02:47 -04:00
Kelvin Sherlock
c03f888032 update slots for MAME 0.253 2023-03-30 21:31:13 -04:00
Kelvin Sherlock
2b127ac5a8 version bump 2023-03-01 18:01:45 -05:00
Kelvin Sherlock
c6edfe91f2 fix bgfx; as of 0.252, -video bgfx is required. also, add Fighters effect 2023-03-01 10:56:45 -05:00
Kelvin Sherlock
11ba25588b version bump 2023-02-28 17:30:45 -05:00
Kelvin Sherlock
695ed00552 bump sdl version 2023-02-28 15:41:03 -05:00
Kelvin Sherlock
c8e3c95240 version bump for -wip mame. 10.13 now required 2023-01-14 10:20:28 -05:00
Kelvin Sherlock
4acd3d51a7 bump version 2022-12-31 13:44:22 -05:00
Kelvin Sherlock
93cb6c5276 bump version 2022-11-30 10:01:25 -05:00
Kelvin Sherlock
52e9f00b92 mame 250 device updates 2022-11-29 18:26:45 -05:00
Kelvin Sherlock
453e2bd497 version bump 2022-10-31 23:58:37 -04:00
Kelvin Sherlock
c722b28ef3 add mac color classic, lc520 to ample project. 2022-10-31 17:57:27 -04:00
Kelvin Sherlock
7a077e5ec8 add mac color classic and lc 520 (mame 249) 2022-10-31 17:47:10 -04:00
Kelvin Sherlock
436694a0b6 version bump 2022-09-28 18:52:20 -04:00
Kelvin Sherlock
01e36939aa use sparkle 2.2.0 2022-09-28 18:41:17 -04:00
Kelvin Sherlock
20c767021c mame 248 update - apple iic+ disk drive change 2022-09-28 14:12:00 -04:00
Kelvin Sherlock
b64ca73346 version bump 2022-09-01 19:12:05 -04:00
Kelvin Sherlock
62767971ee don't crash if a slot is empty (laser3000, which has no slots and no disk drives) 2022-09-01 18:35:33 -04:00
Kelvin Sherlock
6b2c4c408a remove software list is hidden binding (it's set explicitly in the controller) 2022-09-01 18:31:12 -04:00
Kelvin Sherlock
bbcc41cc10 laser 3000 does not have ram options. quick fix until fixed. 2022-09-01 18:24:33 -04:00
Kelvin Sherlock
f651ca6b26 project update 2022-09-01 17:45:20 -04:00
Kelvin Sherlock
16036d9df0 add laser 3000 2022-09-01 17:45:20 -04:00
Kelvin Sherlock
41653fcae1 MAME .247 update 2022-09-01 17:45:20 -04:00
Kelvin Sherlock
87b4cc9494 version bump (u2 #2) 2022-09-01 17:45:20 -04:00
Kelvin Sherlock
9b349e699f version bump 2022-09-01 17:45:13 -04:00
Kelvin Sherlock
03c8306718 .246 - add uthernet, block ATA compact flash 2022-07-31 20:58:28 -04:00
Kelvin Sherlock
41ad1f0d7a version bump 2022-06-30 22:18:32 -04:00
Kelvin Sherlock
d5ed5f74a2 update plists for MAME 0.245 2022-06-30 18:23:10 -04:00
Kelvin Sherlock
2409ad55a1 version bump 2022-05-25 21:33:52 -04:00
Kelvin Sherlock
601e56ccaa bump components date 2022-04-30 15:08:12 -04:00
Kelvin Sherlock
d5d90ba6be version bump. 2022-04-30 10:19:44 -04:00
Kelvin Sherlock
4a0caa2e78 Incomplete - started adding support for "Reinstall MAME components" menu item.
The main holdup is that the software list is loaded from those installed MAME components and reinstalling them would invalidate and require a reload.
2022-04-30 10:17:57 -04:00
Kelvin Sherlock
23a05d5414 support for bios in the slot controller. 2022-04-30 10:16:05 -04:00
Kelvin Sherlock
4ffd8d1f44 move bios settings to be handled as a slot option. 2022-04-30 10:14:37 -04:00
Kelvin Sherlock
f52470eb2e build 27 was 241-1, bump to 28 2022-04-01 11:45:14 -04:00
Kelvin Sherlock
65aedba94b 242 version bump 2022-04-01 09:06:45 -04:00
Kelvin Sherlock
8707b4a246 add move to trash menu option
keep file size (will display later)
2022-03-29 11:57:19 -04:00
Kelvin Sherlock
5a0fdd5a7e add bios options to the machine plist (no gui yet), clean up CFFA name slightly. 2022-03-25 17:20:22 -04:00
Kelvin Sherlock
4e05ff7e8c shift-command-D will update the current bookmark. 2022-03-18 15:23:56 -04:00
Kelvin Sherlock
781d8ada60 midi - representedObject can be reset in some circumstances. (reloading from nib?) use title which seems more permanent. 2022-02-28 10:33:17 -05:00
Kelvin Sherlock
d258fd2a48 midi selection - need to save the current object before destroying the menu. 2022-02-28 09:34:05 -05:00
Kelvin Sherlock
2b2f3a2fd8 software search improvements
1. handle diacritics
2. strip leading "the " from titles and search string since it's often inconsistent
2022-02-26 21:21:27 -05:00
Kelvin Sherlock
9bb0cc468a bump sparkle 2.1.0 2022-02-26 18:45:17 -05:00
Kelvin Sherlock
79c3eba93e software list items need to be *after* slot configuration so they have access to the 3.5" disk controller card, for example. 2022-02-26 15:52:13 -05:00
Kelvin Sherlock
e09a151c91 revert accidental changes to the preference window 2022-02-26 11:35:47 -05:00
Kelvin Sherlock
ce35015218 macos 12 doesn't like singletons in nibs 2022-02-23 22:32:33 -05:00
Kelvin Sherlock
1dd3664a2b version bump - 241 2022-02-23 21:14:30 -05:00
Kelvin Sherlock
0616991a1b - Move bookmarks and disk images to core data
- bookmark edit window
- rom window now shows machine description, tooltip is name
- fix split floppy logic to work with a2superdrive
- fix software list loading from default
- mame 241 machine updates
2022-02-23 20:59:05 -05:00
Kelvin Sherlock
7633887391 bump copyright year. 2022-01-30 12:30:49 -05:00
Kelvin Sherlock
c49c4df9bf WIP version bump 2022-01-15 10:54:34 -05:00
Kelvin Sherlock
eda219faa2 Tested and excluded extra CD ROM devices.
They were previously excluded from the machine descriptions but
they now need to be excluded from the ROM file as well.
2022-01-15 10:54:18 -05:00
Kelvin Sherlock
5382447dc9 rom/machine updates for 240 (wip) 2022-01-15 10:13:07 -05:00
Kelvin Sherlock
8f989c0d3f sparkle 2.0 2022-01-02 21:59:47 -05:00
Kelvin Sherlock
1141e3da0d version bump (0.239) 2021-12-28 21:50:00 -05:00
Kelvin Sherlock
c5eeec9b6d MAME 239 update 2021-12-28 21:06:03 -05:00
Kelvin Sherlock
2122f0707b Add Franklin ACE 2200 machine definition. 2021-12-02 18:12:24 -05:00
Kelvin Sherlock
809e344a2d add ace 500, move franklin to it's own group, updated machine descriptions 2021-11-29 20:00:46 -05:00
Kelvin Sherlock
405e802176 version bump 2021-11-24 13:04:36 -05:00
Kelvin Sherlock
d352e7c45d Download manager - support for password protected web sites (basic authorization).
Since there's no UI for the username/password, these need to be managed within keychain.

Add a new keychain item with the porotocol + server (ie, https://romz.example.com) as the keychain item name, account name, and password.
2021-11-20 09:43:22 -05:00
Kelvin Sherlock
5af5e2e300 move first responder resignation code to a function. 2021-11-16 22:44:38 -05:00
Kelvin Sherlock
afc3ac608a Downloader: resign first responder before downloading so the URL will update (if it's being edited). 2021-11-16 20:44:11 -05:00
Kelvin Sherlock
c200672650 sparkle update. 2021-11-16 19:15:17 -05:00
Kelvin Sherlock
345d4f3d74 laser128.o rom 2021-10-27 17:15:58 -04:00
Kelvin Sherlock
b795d60995 version bump 2021-10-27 17:12:25 -04:00
Kelvin Sherlock
09b4972084 bump components date 2021-10-27 17:11:00 -04:00
Kelvin Sherlock
49c191bf5f Add laser 128 (original version) 2021-10-27 17:10:43 -04:00
Kelvin Sherlock
7f5efc1479 updated machine descriptions for 0.237 2021-10-27 16:57:56 -04:00
Kelvin Sherlock
c7fa95c918 software list - support for the notes field. 2021-10-06 21:05:58 -04:00
Kelvin Sherlock
7178118ea9 236 version bump 2021-09-29 21:03:55 -04:00
Kelvin Sherlock
e9654f01c0 mame 0.236 updates 2021-09-29 19:50:41 -04:00
Kelvin Sherlock
098b8cb7da update component date 2021-08-26 23:25:05 -04:00
Kelvin Sherlock
35b60b1358 0.235 version bump 2021-08-26 22:06:20 -04:00
Kelvin Sherlock
0c56be79f3 tweak rom build script 2021-08-26 22:06:03 -04:00
Kelvin Sherlock
e66502ea42 update roms and cards for 0235 2021-08-26 22:01:52 -04:00
Kelvin Sherlock
70f4738264 add midi input/output menu. 2021-08-07 15:12:45 -04:00
Kelvin Sherlock
026a9e7704 fix missing key 2021-08-06 21:25:27 -04:00
Kelvin Sherlock
7a482191ab update embedded timestamp / archive url 2021-07-28 16:41:07 -04:00
Kelvin Sherlock
3827cce320 version bump 2021-07-27 23:50:00 -04:00
Kelvin Sherlock
82fbe43795 remove some roms that don't exist (included in other sets) 2021-07-27 23:48:42 -04:00
Kelvin Sherlock
acfc37675b version bump for kfest release. 2021-07-23 21:37:51 -04:00
Kelvin Sherlock
fa64005345 disable the midi in / midi out for now since it's more complicated than I expected. 2021-07-23 21:30:16 -04:00
Kelvin Sherlock
f79fb60883 SoftCard /// 2021-07-23 21:29:13 -04:00
Kelvin Sherlock
d92145f6b4 wrong logic was causing custom mame to be ignored when launching
(but not for shell script).
2021-07-18 21:48:19 -04:00
Kelvin Sherlock
139ab22f2a add -rewind support, increase size of media and slots
rewind saves the state before each step.
2021-07-14 22:38:15 -04:00
Kelvin Sherlock
b58a859398 set the category index to -1 when category not in use. 2021-07-14 19:40:40 -04:00
Kelvin Sherlock
a278f679b0 whitespace 2021-07-14 19:38:52 -04:00
Kelvin Sherlock
0c55214085 midi/picture support. 2021-07-10 23:37:10 -04:00
Kelvin Sherlock
7c704e577d whitespace 2021-07-10 23:35:56 -04:00
Kelvin Sherlock
d52c2cd9d1 updated machine definitions with midi, picture, and lance 2021-07-10 23:35:48 -04:00
Kelvin Sherlock
5aa8990ac6 whitespace 2021-07-10 23:34:00 -04:00
Kelvin Sherlock
82a73ef79c midiin, midiout, and picture support. 2021-07-10 23:33:20 -04:00
Kelvin Sherlock
0d4a08113b media view - store the category in the path control to better identify if it's a disk image. 2021-07-10 12:07:01 -04:00
Kelvin Sherlock
fc3bae79c3 disable all mouse tracking code (which was unused) 2021-07-10 12:05:22 -04:00
Kelvin Sherlock
053b9d84db remove logging, add begin/end updates 2021-07-10 11:25:25 -04:00
Kelvin Sherlock
c7d0a2aecb animate out out the entire category when it's completely invalidated. 2021-07-10 01:45:03 -04:00
Kelvin Sherlock
5a098b9d00 double-clicking a recent disk image will try to put it in an appropriate location.
if the media class doesn't exist (eg, hard drive with no hard drive controller) it's added but not displayed.
2021-07-10 01:15:34 -04:00
Kelvin Sherlock
abf4e027ee improve disk image/etc sniffing. 2021-07-08 22:09:33 -04:00
Kelvin Sherlock
ec020cf028 bookmark duplicate name logic didn't work... 2021-07-07 07:15:28 -04:00
Kelvin Sherlock
9ab4b8373d statusDescription depends on status (and error) 2021-07-02 17:38:36 -04:00
Kelvin Sherlock
796b1f2fc8 reset the software list when loading a bookmark. 2021-07-02 17:16:05 -04:00
Kelvin Sherlock
d7b3c763dd update readme 2021-07-01 21:31:08 -04:00
Kelvin Sherlock
32aad8cb61 updated screenshots 2021-07-01 21:26:24 -04:00
Kelvin Sherlock
1eb3811611 adjust download spinner size and location. 2021-07-01 19:21:51 -04:00
Kelvin Sherlock
ac459adb57 commentary. 2021-07-01 19:21:51 -04:00
Kelvin Sherlock
d058aa6588 233 version bump 2021-07-01 19:10:38 -04:00
Kelvin Sherlock
3889b42c14 add secret listmedia/listslots options in the right-click menu
when option key pressed.
also adjust log window to use monospace font, show error/signal in red, and don't mention a successful exit.
tweaks to file handling/task complete so task complete logic is delayed until file handle is drained.
2021-06-18 21:57:46 -04:00
Kelvin Sherlock
34fcc3b3ed more useful scripts. 2021-06-17 23:44:15 -04:00
Kelvin Sherlock
c10f2153ff unused code to guess what sort of media a disk image is.
The general idea would be drag-n-drop a file (or double-click from the disk image window, etc)
and auto-place it in the right place.
2021-06-17 23:43:31 -04:00
Kelvin Sherlock
23afbd8952 move url update to main thread to prevent core animation mutation errors (???) 2021-06-17 13:25:39 -04:00
Kelvin Sherlock
5fbc00e375 print a descriptive error message when vmnet_helper fails. 2021-06-16 23:47:16 -04:00
Kelvin Sherlock
5dd04cd3b7 Apple III titan card (mame 2.33) 2021-06-16 23:46:47 -04:00
Kelvin Sherlock
27bfc1cd8b default to window mode since it's less surprising 2021-06-16 23:46:26 -04:00
Kelvin Sherlock
800087096d r15 updates 2021-06-16 00:39:10 -04:00
Kelvin Sherlock
669e9a16f4 update floppy lists 2021-06-15 23:57:47 -04:00
Kelvin Sherlock
7c766ba76e codesign mame w/ entitlements
also test code to soft-link mame under a new name.
2021-06-15 19:16:23 -04:00
Kelvin Sherlock
c307ab0403 hardened_runtime/entitlements 2021-06-15 17:09:40 -04:00
Kelvin Sherlock
7d1e1bf6bd update appcast URL. 2021-06-15 16:42:58 -04:00
Kelvin Sherlock
9da9f6bd63 add sparkle framework and check for updates menu item. 2021-06-14 23:11:25 -04:00
Kelvin Sherlock
4144a6ad03 switch media bookmark to use a keyed dictionary instead of an array.
An array is fragile in terms of future proofing if I want to re-arrange the layout.
2021-06-13 21:31:56 -04:00
Kelvin Sherlock
76ac6f777a add bitbanger to machine files 2021-06-13 18:25:26 -04:00
Kelvin Sherlock
6b43c42682 eliminate the bitbanger text field. 2021-06-13 17:21:05 -04:00
Kelvin Sherlock
67f2c60286 method to reset the machine view controller. 2021-06-13 17:17:47 -04:00
Kelvin Sherlock
cae68c7f5a for child options, update the name when updating the keypath so it matches the bookmark data. 2021-06-13 17:17:20 -04:00
Kelvin Sherlock
681c70d515 bookmark wasn't setting child options. 2021-06-13 16:45:01 -04:00
Kelvin Sherlock
7abb2f68a0 use string instead of url for bitbanger slots. 2021-06-13 16:29:16 -04:00
Kelvin Sherlock
4c003007f5 bitbanger support for media.
it still needs work to allow sockets and opt-out of disk image drag-and-drop.
2021-06-13 12:29:23 -04:00
Kelvin Sherlock
a5a6222c9f use bindings for media table views 2021-06-13 12:26:56 -04:00
Kelvin Sherlock
058da073ee move reset slots button to a menu, add options to reset slots, media, machine, or everything. 2021-06-12 22:59:19 -04:00
Kelvin Sherlock
5e0d31a772 hide launch/reset slot buttons when not available. 2021-06-12 16:34:07 -04:00
Kelvin Sherlock
e958ffe65a download buttons were inconsistent. 2021-06-12 16:18:14 -04:00
Kelvin Sherlock
2b0e6d4d9d macOS 11 UI fixes. macOS 11 is kind of ugly, tbh. 2021-06-12 16:06:56 -04:00
Kelvin Sherlock
33d6c651d0 reset more things when no default. 2021-06-12 16:03:55 -04:00
Kelvin Sherlock
0381037356 when loading a bookmark/defaults, don't mark default slot values as explicit. 2021-06-12 14:43:58 -04:00
Kelvin Sherlock
c4c2defc01 save/restore/autoload default support. 2021-06-12 14:02:11 -04:00
Kelvin Sherlock
46fe931103 default to no disk drive samples because it's starting to annoy me. 2021-06-12 14:01:42 -04:00
Kelvin Sherlock
141877f8cb adjust machine outline view positioning 2021-06-09 23:40:24 -04:00
Kelvin Sherlock
e9d348ec71 mameMachine -> machine
also add machine name to window title.
2021-06-09 22:47:00 -04:00
Kelvin Sherlock
37b085e45f hide tabview when machine is null. 2021-06-09 22:05:32 -04:00
Kelvin Sherlock
7af810d14f fix leading warning 2021-06-09 22:04:43 -04:00
Kelvin Sherlock
884f8b190a use arranged objects as source of truth for clickedItem. 2021-06-09 22:02:50 -04:00
Kelvin Sherlock
7b55c37128 machine view - clicking a parent-only row will toggle expansion
also add animation proxy to bookmark code
2021-06-09 22:01:43 -04:00
Kelvin Sherlock
c0534f0107 auto-resize views to match launch window view sizes. 2021-06-09 00:11:25 -04:00
Kelvin Sherlock
69f56830ca replace machine browser with outline view 2021-06-08 22:40:20 -04:00
Kelvin Sherlock
b8697d326c recent disk images - add back highlighting. 2021-06-07 23:27:25 -04:00
Kelvin Sherlock
ef2bbeb9c3 Squashed commit of the following:
commit c41312ac604526fbfa8eb9c70c26afb5711531ed
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon Jun 7 22:55:43 2021 -0400

    replace custom table delegate/datasource with array controller

    required a few tweaks to get the binding correct and equivalent to the hand-rolled version.

    The only advantage is the filtering capability (currently All/Missing)

    Also, refreshing didn't update the status and url if the local file had been deleted.

commit 3aedf237344fa9fbb8225cf3513a27da9647ea07
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon Jun 7 21:13:39 2021 -0400

    add toolbar and array controller to filter missing roms, etc.
2021-06-07 22:56:55 -04:00
Kelvin Sherlock
3d5a2951bb Squashed commit of the following:
commit 78c81626670fdf41fa6bdd71a4243a89a0746615
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon Jun 7 00:33:48 2021 -0400

    check if software set has a particular entry.

commit ef5ab6b6948dc3bbbe2947ea099fcacd08435e86
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Jun 6 22:20:34 2021 -0400

    fix scroller background on recent disk images window.

commit dee56fa50e87299b396b48361bd0a780aaaaa768
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Jun 6 21:26:23 2021 -0400

    update cheat sheet javascript to work with 10.11
    * => functions not supported
    * NodeList.prototype.forEach not supported.

commit b00cc05413f4ebd6d6d58f96e24303008608f3a6
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Jun 6 17:10:41 2021 -0400

    default full machine name for bookmark entry.

commit a671cafdc98051b56b12cdd3ccd13c22f54f605a
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Jun 6 15:39:32 2021 -0400

    loading a bookmark wasn't updating the media.

commit 3000e0eb1b10bede3345aaab8478e9ec209f328c
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Jun 6 15:38:53 2021 -0400

    bump copyright year.

commit 45222dacd4aa0047fae63a9112509de57139df63
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Jun 6 13:38:23 2021 -0400

    add reset w/ value for setting the item explicitely.

commit cc7fde1253b71c4d8655eb4c010bbf4e61333a15
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Jun 6 13:37:48 2021 -0400

    add checkboxes for bitbanger/share directory.

    The general idea is it's easier to toggle a checkbox than to type/retype a path.

commit 5674b2d7f6b0e2f0b973197bf3493ad61bf46428
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sat Jun 5 19:11:43 2021 -0400

    commentary on searches with diacritics.

commit ec60634dcd9c573130dc34673b4d3fe597ea2b42
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sat Jun 5 19:11:22 2021 -0400

    clean up auto-complete a little bit when setting a value directly.

commit 1a182bbdab237c89d355d8294b5a4a64b785783a
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sat Jun 5 13:08:29 2021 -0400

    fix text color when value is set.

    There are still some bugs relating to multiple copies of the value being stored.

commit 49c0bc15c73446259d8cc151cf52d6058644db76
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sat Jun 5 12:09:44 2021 -0400

    reset all controls first.

commit 059797ad85b057e296cc707b4645f839bfccac13
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sat Jun 5 10:52:06 2021 -0400

    more bookmark loading.

commit e5a612d9f8e7414dd15c66dbaa540b637765eeec
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Jun 4 23:52:38 2021 -0400

    bookmark - restore the software

commit f9411a1e84df7bd46e352cc5ca995b585c2a0523
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Jun 4 23:52:25 2021 -0400

    clean up software / name logic.

commit f628d99e4a
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Jun 4 00:21:08 2021 -0400

    load bookmark...

commit 0b248e6aad
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri Jun 4 00:20:42 2021 -0400

    stringValue can't be nil.

commit 94aac38af4
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Thu Jun 3 23:04:37 2021 -0400

    add bookmark menu

commit 6215a0df12
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Thu Jun 3 23:03:29 2021 -0400

    slot view needs to know the machine.

commit d348c15dc5
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Thu Jun 3 23:02:58 2021 -0400

    transformer to enable/disable control based on string length.

commit e14336a009
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Thu Jun 3 23:02:14 2021 -0400

    shut up compiler warning.

commit 4baf545245
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Thu Jun 3 23:01:15 2021 -0400

    bookmark manager

commit 0f3e6c8307
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon May 31 23:54:29 2021 -0400

    more (untested) bookmark code

commit 8fdb149eb3
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon May 31 16:13:43 2021 -0400

    start of bookmarking support. Untested.

commit 787eac87f6
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon May 31 16:12:45 2021 -0400

    shut up warnings about content clipping.
    maybe it's a 10.11 thing.  The size was chosen by interface builder.
2021-06-07 00:34:26 -04:00
Kelvin Sherlock
789d61d9f1 when launching, clear the first responder so any text fields with focus will commit. 2021-05-31 11:24:33 -04:00
Kelvin Sherlock
5ffc85f9fc 10.13+ launch wasn't. 2021-05-31 10:39:24 -04:00
Kelvin Sherlock
7b67522156 fix bitbanger / shared directory placeholders. 2021-05-30 22:22:13 -04:00
Kelvin Sherlock
f14b291e60 fix auto-complete menu (remove show title setting) 2021-05-30 20:41:36 -04:00
Kelvin Sherlock
576931cd71 add interface for -share_directory (booti) and -bitbanger (null modem) 2021-05-30 18:46:46 -04:00
Kelvin Sherlock
9ed83bf316 NewSlotView -> SlotView 2021-05-30 18:19:51 -04:00
Kelvin Sherlock
751083ea26 remove old slot view controller code/nib 2021-05-30 18:14:55 -04:00
Kelvin Sherlock
1b7faf3ac4 Updates to work with 10.11 (El Capitan) and newer.
There are still a couple minor UI degradations

eg: mame cheat sheet, recent disk images window, auto complete window.

Squashed commit of the following:

commit fb115024f805da38b747fd1905573fabb7bff24e
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 18:00:13 2021 -0400

    ?

commit 8405f4df95ae8f5bc5dc33598dc0b3f8972b32cd
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 17:59:43 2021 -0400

    tintColor not present before 10.14

commit 86a6102cee4f30cac2972259ef55fda3c32b8f9a
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 17:59:19 2021 -0400

    [menu setItemArray:] apparently has problems before 10.14

commit 65227a00743fbf143c623af8a76698d57bdc4573
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 17:58:15 2021 -0400

    NSCache doesn't like null objects.

commit 8a4c3a4662647d5ee0b609bde9f3aaa5c0d99776
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 16:00:05 2021 -0400

    organize copy bundle resources.

    multiple-sized png images are converted to a single tiff (with multiple sizes).
    This is fine BUT EL capitan grabs the first image so if the @3x image is first, it will be used.

commit 44b94cdfd47117864b6529214b1c91a0c2e41327
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 15:57:37 2021 -0400

    add NewSlotViewController.m to Ample Lite.

commit 2fa1b7418783e48ca625ab3490e43cbff9e5619a
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 13:57:19 2021 -0400

    Ample Lite was missing reference to New Slot View nib.

commit 65f268e77a65f8c57019702d8f0c2b66577c5ee7
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 13:56:04 2021 -0400

    based on testing, 10.11 still has public.file-url, which is kUTTypeFileURL.  10.13 added NSURLPBoardType as a synonym.

commit cde123b16eb336b7695b444931b9e9bb9802d772
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 30 13:54:02 2021 -0400

    set everything to 10.11

commit e7a670efd3
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sat May 29 23:33:31 2021 -0400

    script to download SDL2.Framework

commit 9f38f2972a
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sat May 29 22:15:32 2021 -0400

    WKWebView apparently has a bug prior to 10.12 so it can't be created via a nib.

commit e18aea7249
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sat May 29 22:14:38 2021 -0400

    version checks for features not present in 10.11

commit 07dcf30f52
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Fri May 28 21:30:53 2021 -0400

    lower target to 10.11
2021-05-30 18:00:34 -04:00
Kelvin Sherlock
bfbac2cc20 adjust media view nib to match the reduced size. 2021-05-28 21:29:54 -04:00
Kelvin Sherlock
3bf2f63bf6 really make scroller background transparent. 2021-05-28 21:29:27 -04:00
Kelvin Sherlock
6468ee2629 bump mame components date 2021-05-27 20:36:57 -04:00
Kelvin Sherlock
5f84c4b2c1 remove logging 2021-05-27 20:36:24 -04:00
Kelvin Sherlock
8944c88339 bump version 2021-05-27 20:36:01 -04:00
Kelvin Sherlock
3d4d0c92c7 Squashed commit of the following:
commit 1dd1d6d3eee928d283dafbaf4432b053dff65ac2
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Thu May 27 13:30:38 2021 -0400

    0.232 rom update

commit cfb7f9a4d1647c41fab3328bada0f37bdb041983
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Wed May 26 20:31:16 2021 -0400

    fix resizing to prevent horizontal scrolling

commit 5c393ab5a95c9e53c4ef1e0b3f2b77db93e1c29b
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Wed May 26 20:01:48 2021 -0400

    esc should close the menu if visible, otherwise clear the text.

commit 7da142b64280c39e216584cedb7fb14243d573f0
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Tue May 25 23:17:10 2021 -0400

    show software short name unless it's ambiguous.

commit 6f3b3bef5e18e78619959613e28064eb6251ce27
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Tue May 25 23:16:47 2021 -0400

    cleanup some auto complete rough edges

commit 4988d8b266b8b11e519bcb5aab05ad2c3ffe5c23
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Tue May 25 23:16:24 2021 -0400

    fix

commit 6d4bf94fd6b4850564b705ea15e91079b00346c2
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Tue May 25 19:13:28 2021 -0400

    clean up autocomplete a little...

commit 3722271e51d93599903bccc721dc1de61f0aae72
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Tue May 25 19:13:07 2021 -0400

    move auto complete logic to SoftwareSet

commit 04cc83ecbe9ee4c9100305712c47a11359327734
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon May 24 20:46:39 2021 -0400

    software - keep the list name to differentiate in case of name clashes.

commit 8e5b5dc7e283f760a16011308298e999110fc052
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon May 24 20:45:13 2021 -0400

    Autocomplete - limit menu content width to the clip view content width.

    prevents horizontal scrolling.

commit 356048d450447485bb33a4261018f85dac19a134
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon May 24 18:45:42 2021 -0400

    add auto complete software list to the launch window.

commit 9dc72b702c9b36d490349f291c10b98b56178567
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon May 24 18:44:28 2021 -0400

    autocomplete control.

commit 40eee83f56d957c64e0f8d927486f13165b9e120
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon May 24 18:39:32 2021 -0400

    add filters to software list.

commit cebfbaa545441f061cffafe8ca93db2377240a06
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun May 23 11:59:00 2021 -0400

    add compatibility field for software list filtering.
2021-05-27 19:42:28 -04:00
Kelvin Sherlock
e48e2a9223 add mac 68k wiki link 2021-05-18 17:51:53 -04:00
Kelvin Sherlock
a8e03a9490 support for -share_directory (booti card). No UI support yet, though. 2021-05-16 11:06:12 -04:00
Kelvin Sherlock
5e87627251 log window - add button to clear the log 2021-05-16 11:00:33 -04:00
Kelvin Sherlock
41de913e5f a2 - booti card. mac - built-in scsi now configurable, remove oddball cd devices 2021-05-16 00:21:15 -04:00
Kelvin Sherlock
5f3c346562 new mame archive.org link and components date 2021-04-28 23:54:09 -04:00
Kelvin Sherlock
d992b6960d bump version, change numbering to match embedded MAME 2021-04-28 23:23:51 -04:00
Kelvin Sherlock
bc9e156af0 mame 0.231 update 2021-04-28 23:18:41 -04:00
Kelvin Sherlock
9be960bb8e project fix for archiving. 2021-03-30 22:20:45 -04:00
Kelvin Sherlock
f3680e0309 version bump 2021-03-30 22:12:27 -04:00
Kelvin Sherlock
2465b38916 commentary. 2021-03-30 21:21:30 -04:00
Kelvin Sherlock
cafecda333 switch the default mac II from mac lc to mac iix 2021-03-30 21:21:12 -04:00
Kelvin Sherlock
2e6edaba1b add back the software list. 2021-03-28 18:50:55 -04:00
Kelvin Sherlock
94dfbc6e3e mac2fdhd needed as parent of se/30, etc. 2021-03-26 22:21:56 -04:00
Kelvin Sherlock
821a84923f add new machine definitions 2021-03-26 22:13:59 -04:00
Kelvin Sherlock
311a3461f6 add some more macintosh models
also change the default compact model from mac128 to macse30
2021-03-26 22:06:39 -04:00
Kelvin Sherlock
88c12a4832 add pty_shell command.
note that c modules had to be disabled in the build settings due to #define TTYDEFCHARS.
2021-03-26 21:16:18 -04:00
Kelvin Sherlock
6ca897739a add support for mac 128k family 2021-03-19 17:24:38 -04:00
Kelvin Sherlock
2a0462cc41 sort slots by name in the plist files. 2021-03-19 17:23:41 -04:00
Kelvin Sherlock
fe0d690f87 improved submachine loading and more slot options for cards 2021-03-19 16:46:32 -04:00
Kelvin Sherlock
ffb76a31f9 caution image - not yet used. 2021-03-18 23:12:50 -04:00
Kelvin Sherlock
123a51d52f transparent scroller 2021-03-15 16:43:12 -04:00
Kelvin Sherlock
f89c932b77 disk drive slot
3.5" and 5.25" floppy drives that are configurable via a slot now have a UI in Ample.

<device> media (//c+, a2diskii, mac*, cassettes, etc) are not adjustable.
2021-03-14 16:02:53 -04:00
Kelvin Sherlock
0d13fa7167 add tk3000 2021-03-14 13:23:43 -04:00
Kelvin Sherlock
e1eecac557 add lcd-grid filter 2021-03-13 15:44:52 -05:00
Kelvin Sherlock
f8b3a1d882 integer x 2021-03-13 11:26:17 -05:00
Kelvin Sherlock
9e5b8d45ca source list highlighting on the rom list 2021-03-13 11:23:46 -05:00
Kelvin Sherlock
e975980a3a tweak the disk images colors a little bit 2021-03-13 11:16:49 -05:00
Kelvin Sherlock
6177001a4c -nosample support to eliminate disk sound effects. 2021-03-12 20:09:59 -05:00
Kelvin Sherlock
b2907eda08 update rom list. 2021-03-12 19:58:44 -05:00
Kelvin Sherlock
48cdd702be pop up for child slots. 2021-03-12 19:58:12 -05:00
Kelvin Sherlock
2f514a1db3 stat working on a pop up for card slots 2021-03-10 18:37:59 -05:00
Kelvin Sherlock
d37fb49781 display slot submenus. i don't particularly like the UI so it will probably change soon. 2021-03-09 22:58:01 -05:00
Kelvin Sherlock
34970cb476 move slots (and ram) into a slots bucket in the machine description. devices with media are also includes (in the device bucket).
In preparation for a UI to edit the subslots.
2021-03-09 22:22:24 -05:00
Kelvin Sherlock
9626a6588f base the export shell script default name on the machine name. 2021-03-08 21:15:15 -05:00
Kelvin Sherlock
dc7adde938 auto set the rpath in mame64.
I would prefer to do it after copying but the copy also codesigns.
2021-03-08 19:42:12 -05:00
Kelvin Sherlock
328ab815fb Squashed commit of the following:
commit a91a858d68c845f74db106dd21a800c4d09e6e38
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Mar 7 22:49:42 2021 -0500

    listxml utility.

commit e52576797da2609e700a12d1ffd7c78e8f1c2b23
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Mar 7 22:34:00 2021 -0500

    update media to use a structure instead of passing around dictionaries.

commit 9277a0f720091c386812ac5f84d96080fe6e14f3
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Mar 7 20:13:27 2021 -0500

    media is working again.

commit 7c0ac9a973df85fdcdaa978f80905cb9e8532ea5
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Mar 7 18:46:38 2021 -0500

    use new slot objects [WIP]

commit 005e2f14d37e7b83ac4ab3e60e7fb794ac8ed651
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Mar 7 17:33:59 2021 -0500

    new slot code to make sub options easier.

commit d7f3d9ef75367fad15081789a33212b7cf928fb3
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Sun Mar 7 17:33:13 2021 -0500

    String Interning...
2021-03-08 18:59:02 -05:00
Kelvin Sherlock
d433920740 version bump 2021-02-24 17:38:16 -05:00
Kelvin Sherlock
5d5c477bee disable developer menu for mame cheat sheet 2021-02-24 17:38:05 -05:00
Kelvin Sherlock
4676c7c1ba add webkit framework so the mame cheat sheet will work. 2021-02-24 17:37:29 -05:00
Kelvin Sherlock
760f9e6693 Add a cache for the machine description. 2021-02-23 22:47:43 -05:00
Kelvin Sherlock
5f8b00f021 updated machine descriptions (radio shack printer, software list) 2021-02-23 22:47:22 -05:00
Kelvin Sherlock
750df30533 .229 iigs floppy disk changes 2021-02-23 22:47:15 -05:00
Kelvin Sherlock
9a7b5e6af0 add the software list to the machine description 2021-02-23 22:47:07 -05:00
Kelvin Sherlock
521d33ba55 script to auto-generate rom list.
Found a few missing in the process.
2021-01-29 20:12:26 -05:00
Kelvin Sherlock
4c1541a7da export shell script support. 2021-01-29 20:07:44 -05:00
Kelvin Sherlock
29cfb6c2a0 unify path functions 2021-01-29 20:07:11 -05:00
Kelvin Sherlock
f74f5aaf11 version bump to 10 2021-01-27 22:30:35 -05:00
Kelvin Sherlock
e3edc368fe include signal number when killed by a signal 2021-01-27 18:23:25 -05:00
ksherlock
9323151102
Create xcodebuild.yml 2021-01-20 13:15:50 -05:00
Kelvin Sherlock
6acbadb195 add macintosh warning from David Ryskalczyk 2021-01-18 16:01:36 -05:00
Kelvin Sherlock
3a03b2180a MAX_SLOTS -> SLOT_COUNT 2021-01-18 15:46:07 -05:00
Kelvin Sherlock
52d140d07d macs - add pseudo disk images, remove cd roms (since not usable) 2021-01-18 15:32:59 -05:00
Kelvin Sherlock
0c7c9e9d1b support for nubus mac pseudo disk images 2021-01-18 15:32:22 -05:00
Kelvin Sherlock
dc5ab08d4b add maclc2, maclc3, and maciici (plus nubus roms)
which are reportedly also usable.
2021-01-18 14:47:00 -05:00
Kelvin Sherlock
c51ae648d9 add nubus slots (in case they're ever needed.) 2021-01-17 01:19:11 -05:00
Kelvin Sherlock
74c67be366 move slot size to a macro. 2021-01-17 01:05:02 -05:00
Kelvin Sherlock
bfa371ec0c macintosh lc support 2021-01-17 00:56:42 -05:00
Kelvin Sherlock
2046eed6f4 add mame cheat sheet. implemented in html :/ 2021-01-17 00:47:05 -05:00
Kelvin Sherlock
28b1074da2 version bump 2021-01-06 21:25:57 -05:00
Kelvin Sherlock
40336585b3 add Apricon Super Serial Imager card 2021-01-06 21:25:48 -05:00
Kelvin Sherlock
07d0e78d04 use mame 224 internet archive rom set
since it's currently the newest available and seems less likely to
spontaneously disappear.
2021-01-06 21:24:01 -05:00
Kelvin Sherlock
c88fe397f7 fix log window to work better in dark mode. 2021-01-02 11:43:07 -05:00
Kelvin Sherlock
e86b5c3236 version bump 2020-12-31 17:36:19 -05:00
Kelvin Sherlock
6f8e2d806b add new 0.227 rom files 2020-12-31 17:36:00 -05:00
Kelvin Sherlock
7286ae4f5a update machines for 227 2020-12-29 19:21:49 -05:00
Kelvin Sherlock
7587f8c5ef add wiki menu link 2020-12-29 18:04:02 -05:00
Kelvin Sherlock
93b9995260 release 8 2020-10-28 16:55:40 -04:00
Kelvin Sherlock
dd1263a31c 226 rom url live 2020-10-28 16:55:23 -04:00
Kelvin Sherlock
ed88a87b69 new roms for 226 2020-10-28 00:12:28 -04:00
Kelvin Sherlock
6e4a516610 (better late than never) 225 rom URL 2020-10-28 00:12:03 -04:00
Kelvin Sherlock
6ca8ae2dc9 mame 226 slot updates. 2020-10-25 18:49:31 -04:00
ksherlock
c40f1e621d
Update README.md 2020-10-05 15:40:39 -04:00
Kelvin Sherlock
b089220d81 add a2sider roms (mame 225). 2020-10-04 14:59:03 -04:00
Kelvin Sherlock
c92ab50079 MAME documentation menu item. 2020-10-04 14:53:20 -04:00
Kelvin Sherlock
a3f96076f5 Dark mode - replace redColor w/ systemRedColor
also replaced blackColor w/ nil.
2020-10-04 11:47:50 -04:00
Kelvin Sherlock
d06bf9b1d6 download manager improvements
- better dark mode support
- open roms button
- refresh button
- UI to specify file location and file extension
- check for 404, etc errors which aren't auto converted to an NSError.
2020-10-04 00:16:32 -04:00
Kelvin Sherlock
f9d4489e48 add download url / extension fields. 2020-10-03 14:34:21 -04:00
Kelvin Sherlock
cabffd23ea move italic menu item to public function. 2020-10-03 14:33:51 -04:00
Kelvin Sherlock
170a3864fe Add Ample Support Directory... menu 2020-10-03 12:46:19 -04:00
Kelvin Sherlock
3c81d4d2ce tweak rom url, log download errors. 2020-10-01 13:11:13 -04:00
Kelvin Sherlock
1022ebcbba -skip_gameinfo for vgmplay. 2020-09-30 23:06:44 -04:00
Kelvin Sherlock
32d6cdf004 futz with project so archive works correctly w/ vmnet embedded. 2020-09-30 23:02:53 -04:00
Kelvin Sherlock
f72bed14a5 version bump 2020-09-30 22:09:35 -04:00
Kelvin Sherlock
57a7e24d21 added working directory option for custom mame config.
also log path/working directory to the log window.
2020-09-30 21:49:06 -04:00
Kelvin Sherlock
f3137585c1 silly tweaks for the auth commands.
When stepping in the debugger, it works fine.
When running normally, the second command has a tendency not to run.
adding a file pointer AND reading from it seems to allow the second
command to run more consistently.
2020-09-30 19:19:03 -04:00
Kelvin Sherlock
6e7acb88e2 add drag-drop dock support for launching vgm files
via mame vgmplay
2020-09-30 19:15:37 -04:00
Kelvin Sherlock
5840c4ae0c add roms for vgmplay driver. 2020-09-29 23:29:23 -04:00
Kelvin Sherlock
0c8587beb5 add .raw as supported extension. 2020-09-28 22:59:27 -04:00
Kelvin Sherlock
9f6870585f replace mame command line NSTextField with NSTextView
this adds overflow scrolling.
2020-09-27 23:19:50 -04:00
Kelvin Sherlock
4425fe33f8 bind the media eject button.
contentTintColor is not exposed in interface builder, otherwise it could
all be handled there.
2020-09-27 22:06:03 -04:00
Kelvin Sherlock
68136487ff a2sider1/a2sider2 roms
these files are not readily available yet the cards are
disabled since they're not normal disk images.
2020-09-26 15:21:28 -04:00
Kelvin Sherlock
5745a99ea2 commentary 2020-09-26 14:51:52 -04:00
Kelvin Sherlock
484dd39b67 update machine list.
- cffa2000 renamed to cffa 2.0
- sider1/sider2 added (but disabled)
2020-09-26 14:51:46 -04:00
Kelvin Sherlock
ad12d40052 slot 3 mis-interpreted as slot 2 2020-09-26 11:51:39 -04:00
Kelvin Sherlock
e1a3d39021 add button to set owner and +s permissions on the vmnet_helper app.
this relies on deprecated functionality yet it's the easiest way to do it.

At some point, should try to move vmnet_helper to be a launchd service
which is the preferred way to do rooty things.
2020-09-25 23:38:36 -04:00
Kelvin Sherlock
0befba12a5 xcode project update. 2020-09-25 21:10:36 -04:00
Kelvin Sherlock
13d78a94ed Merge images-window into master 2020-09-25 20:50:35 -04:00
Kelvin Sherlock
4bfc4c027f xebec/sider slots are non-standard disk images. 2020-09-25 20:50:14 -04:00
Kelvin Sherlock
f90f5a6bf3 window restoration support.
only applies if you option quit (quit and save windows) or quit unexpectedly.
2020-09-25 20:46:25 -04:00
Kelvin Sherlock
ecfd5fb7a8 adjust window positions, add frame auto-save 2020-09-18 13:35:04 -04:00
Kelvin Sherlock
7a085301cf drag-and-drop - export urls to other applications. 2020-09-18 00:33:02 -04:00
Kelvin Sherlock
bf619da42d eject / show in finder menu for disk images. 2020-09-15 23:44:24 -04:00
Kelvin Sherlock
d5d869a407 check filetypes when drag-n-dropping to the recent window.
alt skips filetype check.
2020-09-15 23:11:20 -04:00
Kelvin Sherlock
59ce93bbc0 add some duplicate filtering when adding a disk image to the recent list. 2020-09-15 21:56:10 -04:00
Kelvin Sherlock
0d88e3e93a put all recent disk image logic in the recent disk image window controller. 2020-09-15 21:39:14 -04:00
Kelvin Sherlock
4ca9d2caaf fix casette spelling 2020-09-15 18:03:05 -04:00
Kelvin Sherlock
531c3096e9 drag-n-drop files to the recent disk images list. 2020-09-14 21:03:09 -04:00
Kelvin Sherlock
376f808d29 disk images window [WIP].
uses bound nsarray controller.
2020-09-14 21:03:09 -04:00
Kelvin Sherlock
97c27328d0 Add 3x window size option. 2020-09-14 19:09:10 -04:00
Kelvin Sherlock
0dfd7c0605 new screenshot. 2020-09-14 18:38:14 -04:00
Kelvin Sherlock
afa29a9e91 bump version. 2020-09-14 18:24:21 -04:00
Kelvin Sherlock
65a1a9e6c6 move agat 7/9 to their own category since they are
very different.  adjusted clone category list a little bit,
2020-09-14 18:24:21 -04:00
Kelvin Sherlock
7ef1edfe81 Add some pretty icons... 2020-09-13 14:30:40 -04:00
Kelvin Sherlock
2ab55c0454 minor fixes
1. remove old and unused properties
2. add mouse capture checkbox
3. disable square pixels checkbox in full screen mode
2020-09-13 12:04:54 -04:00
Kelvin Sherlock
8362692523 use some pretty animations when drag/dropping media. 2020-09-12 19:24:32 -04:00
Kelvin Sherlock
416310fe69 adjust media constraints since they were acting stupid at times. 2020-09-12 18:41:00 -04:00
Kelvin Sherlock
9d8f645c69 new slot view - tweak cell size and remove menu auto enable. 2020-09-12 18:35:06 -04:00
Kelvin Sherlock
9946d341a7 eliminate the format menu, move rom management to the window menu. 2020-09-12 18:34:26 -04:00
Kelvin Sherlock
b2bfb6ea11 media view nib - remove focus ring 2020-09-12 18:02:01 -04:00
Kelvin Sherlock
c6bd70f9ef download window - show missing ROMs in red. 2020-09-12 18:01:32 -04:00
Kelvin Sherlock
d8f0794679 change laser order. 2020-09-12 18:01:08 -04:00
Kelvin Sherlock
09b9830840 add agat_fdc to rom list. 2020-09-12 18:00:50 -04:00
Kelvin Sherlock
6452cf5e0a switch to new slot view. 2020-09-12 18:00:34 -04:00
Kelvin Sherlock
d7ffdd841a build fixes for New Slot View 2020-09-12 18:00:09 -04:00
Kelvin Sherlock
9905ddf96e switch ram options to be more consistent with slots. 2020-09-12 17:58:49 -04:00
Kelvin Sherlock
95c7a77982 new slot controller [wip] 2020-09-10 22:06:41 -04:00
Kelvin Sherlock
8b901fc415 tweak -nounevenstretch 2020-09-07 22:20:26 -04:00
Kelvin Sherlock
2ba85fc3f8 move the tabs around a bit. 2020-09-07 22:10:37 -04:00
Kelvin Sherlock
49e2462b28 adjusted launch window window size settings. 2020-09-07 22:00:10 -04:00
Kelvin Sherlock
a829b4feea tweak eject button tracking instantiation 2020-09-07 17:08:42 -04:00
Kelvin Sherlock
0a78177485 Eject button - fix image when enabled status changes and mouseover active. 2020-09-07 15:01:36 -04:00
Kelvin Sherlock
5d54bbd636 re-order tabs. 2020-09-07 14:30:44 -04:00
Kelvin Sherlock
531cee122b Eject Button class. switches to the alt image when hovering. 2020-09-07 14:30:31 -04:00
Kelvin Sherlock
e9fff9aa08 added some artwork for the drag indicator and the eject buttons. 2020-09-06 20:12:21 -04:00
Kelvin Sherlock
ee02dee982 I figured out bgx enough to add some options. 2020-09-06 15:26:20 -04:00
Kelvin Sherlock
9a64879336 bold the media category title. 2020-09-06 11:29:17 -04:00
Kelvin Sherlock
f45db5383d only show the media drag handle when moused over. 2020-09-06 11:25:59 -04:00
ksherlock
4b34ff977d
Update README.md 2020-09-06 01:12:44 -04:00
ksherlock
2fa6a90374
Update README.md 2020-09-06 01:10:02 -04:00
Kelvin Sherlock
7b41e5bf46 updated screenshot 2020-09-06 01:05:57 -04:00
Kelvin Sherlock
f2b08c45a3 clean up item moves a bit.
also switch media to be a mutable array (which it secretly was) and
modify in-place to be cleaner.
2020-09-06 00:31:09 -04:00
Kelvin Sherlock
498fd337eb version bump. 2020-09-06 00:02:27 -04:00
Kelvin Sherlock
3cdae0e386 finish up drag-n-drop 2020-09-05 23:58:03 -04:00
Kelvin Sherlock
9eb3727e1e drag-n-drop disk image re-ordering. WIP. 2020-09-05 23:29:30 -04:00
Kelvin Sherlock
af3ad78b94 update machines for current mame.
tweaks description of mockingboard, adds gizmo, uthernet, cms scsi
2020-09-05 17:35:19 -04:00
Kelvin Sherlock
8906d7825f more launch window tweaks. 2020-09-05 11:00:29 -04:00
Kelvin Sherlock
be04b5a00b apple2c was missing 5.25" drives. 2020-09-05 10:59:38 -04:00
Kelvin Sherlock
8e7e6fa396 update the built-in media list. previous logic was incorrect and
excluded apple 3 floppies (which are actually in slots 0,1,2, and 3)
and included and extra cassette for the Apple 1.
2020-09-05 01:20:28 -04:00
Kelvin Sherlock
ad33f06f98 download window - decrease size of status text. 2020-09-04 23:40:06 -04:00
Kelvin Sherlock
3c77f0a309 media view - only enable eject button when there's something to eject. 2020-09-04 23:39:10 -04:00
Kelvin Sherlock
69023c4af3 tweak layout sizes a bit. 2020-09-04 19:22:18 -04:00
328 changed files with 691263 additions and 134199 deletions

19
.github/workflows/xcodebuild.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: xcodebuild
on: [push, pull_request]
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: build
run: xcodebuild -project "Ample.xcodeproj" -target "Ample Lite" | xcpretty
- uses: actions/upload-artifact@v3
with:
name: Ample Lite
path: build/Release/

3
.gitignore vendored
View File

@ -1,6 +1,9 @@
dist
embedded/mame64
embedded/SDL2.framework
embedded/Sparkle.framework
embedded/Sparkle-*
embedded/SDL2-*
build
embedded/mame-data.tgz
__pycache__

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,8 @@
<dict>
<key>Ample Lite.xcscheme_^#shared#^_</key>
<dict>
<key>isShown</key>
<true/>
<key>orderHint</key>
<integer>1</integer>
</dict>
@ -24,6 +26,36 @@
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>pty_shell.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>3</integer>
</dict>
<key>vmnet_helper.xcscheme_^#shared#^_</key>
<dict>
<key>isShown</key>
<true/>
<key>orderHint</key>
<integer>2</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>B6841BCF251EC913006A5C39</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>B6BA257A24E99BE9005FB8FF</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>B6E4B5AE24FDE2670094A35C</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@ -4,6 +4,8 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>

View File

@ -11,13 +11,46 @@
#import <Cocoa/Cocoa.h>
/* ~/Library/ApplicationSupport/Ample/ */
NSURL *SupportDirectory(void);
NSString *SupportDirectoryPath(void);
/* mame executable URL */
NSURL *MameURL(void);
NSString *MamePath(void);
/* mame working directory */
NSURL *MameWorkingDirectory(void);
NSString *MameWorkingDirectoryPath(void);
NSString *InternString(NSString *key);
NSDictionary *MameMachine(NSString *machine);
/* NSUserDefaults keys */
extern NSString *kUseCustomMame;
extern NSString *kMamePath;
extern NSString *kMameWorkingDirectory;
extern NSString *kAutoCloseLogWindow;
extern NSString *kMameComponentsDate;
extern NSString *kUseLogWindow;
extern NSString *kDownloadURL;
extern NSString *kDownloadExtension;
extern NSString *kDefaultDownloadURL;
extern NSString *kDefaultDownloadExtension;
extern NSString *kNotificationDiskImageAdded;
extern NSString *kNotificationDiskImageMagicRoute;
extern NSString *kNotificationBookmarkMagicRoute;
@protocol Bookmark <NSObject>
-(BOOL)loadBookmark: (NSDictionary *)bookmark;
-(BOOL)saveBookmark: (NSMutableDictionary *)bookmark;
-(void)willLoadBookmark: (NSDictionary *)bookmark;
-(void)didLoadBookmark: (NSDictionary *)bookmark;
@end
#endif /* Ample_h */

View File

@ -35,7 +35,108 @@ NSString *SupportDirectoryPath(void) {
}
NSURL *MameURL(void) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSBundle *bundle = [NSBundle mainBundle];
if ([defaults boolForKey: kUseCustomMame]) {
NSString *path = [defaults stringForKey: kMamePath];
if ([path length]) return [NSURL fileURLWithPath: path];
}
return [bundle URLForAuxiliaryExecutable: @"mame64"];
}
NSString *MamePath(void) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSBundle *bundle = [NSBundle mainBundle];
NSString *path;
if ([defaults boolForKey: kUseCustomMame]) {
path = [defaults stringForKey: kMamePath];
if ([path length]) return path;
}
path = [bundle pathForAuxiliaryExecutable: @"mame64"];
if ([path length]) return path;
return nil;
}
NSURL *MameWorkingDirectory(void) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey: kUseCustomMame]) {
NSString *path = [defaults stringForKey: kMameWorkingDirectory];
if (![path length]) return [NSURL fileURLWithPath: path];
}
return SupportDirectory();
}
NSString *MameWorkingDirectoryPath(void) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey: kUseCustomMame]) {
NSString *path = [defaults stringForKey: kMameWorkingDirectory];
if (![path length]) return path;
}
return SupportDirectoryPath();
}
NSDictionary *MameMachine(NSString *machine) {
static NSMutableDictionary *cache;
if (!cache) cache = [NSMutableDictionary new];
NSDictionary *d;
if (!machine) return nil;
d = [cache objectForKey: machine];
if (d) return d;
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url= [bundle URLForResource: machine withExtension: @"plist"];
d = [NSDictionary dictionaryWithContentsOfURL: url];
if (d) [cache setObject: d forKey: machine];
return d;
}
/* NSCache doesn't retain it's key. This essentially interns it. */
/* could just abuse NSSelectorFromString() */
NSString *InternString(NSString *key) {
static NSMutableSet *storage = nil;
if (!storage) {
storage = [NSMutableSet new];
}
NSString *copy = [storage member: key];
if (!copy) {
copy = [key copy];
[storage addObject: copy];
}
return copy;
}
NSString *kUseCustomMame = @"UseCustomMame";
NSString *kMamePath = @"MamePath";
NSString *kMameWorkingDirectory = @"MameWorkingDirectory";
NSString *kAutoCloseLogWindow = @"AutoCloseLogWindow";
NSString *kUseLogWindow = @"UseLogWindow";
NSString *kMameComponentsDate = @"MameComponentsDate";
NSString *kDefaultDownloadURL = @"DefaultDownloadURL";
NSString *kDefaultDownloadExtension = @"DefaultDownloadExtension";
NSString *kDownloadURL = @"DownloadURL";
NSString *kDownloadExtension = @"DownloadExtension";
NSString *kNotificationDiskImageAdded = @"Disk Image Added";
NSString *kNotificationDiskImageMagicRoute = @"Disk Image Magic Route";
NSString *kNotificationBookmarkMagicRoute = @"Bookmark Magic Route";

26
Ample/AmpleLite.m Normal file
View File

@ -0,0 +1,26 @@
//
// AmpleLite.m
// Ample Lite
//
// Created by Kelvin Sherlock on 6/14/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import <Foundation/Foundation.h>
@class NSMenuItem;
@interface SUUpdater : NSObject
@end
@implementation SUUpdater
- (IBAction)checkForUpdates:(id)sender {
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
return NO;
}
@end

View File

@ -11,6 +11,6 @@
@interface AppDelegate : NSObject <NSApplicationDelegate>
- (IBAction)displayPreferences:(id)sender;
- (IBAction)manageBookmarks: (id)sender;
@end

View File

@ -10,6 +10,14 @@
#import "LaunchWindowController.h"
#import "PreferencesWindowController.h"
#import "DownloadWindowController.h"
#import "DiskImagesWindowController.h"
#import "CheatSheetWindowController.h"
#import "BookmarkWindowController.h"
#import "Transformers.h"
#import "BookmarkManager.h"
#import "LogWindowController.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *installWindow;
@ -20,6 +28,10 @@
NSWindowController *_prefs;
NSWindowController *_launcher;
NSWindowController *_downloader;
NSWindowController *_diskImages;
NSWindowController *_cheatSheet;
NSWindowController *_bookmarks;
}
@ -31,6 +43,10 @@
NSDictionary *dict;
RegisterTransformers();
//BookmarkManager *bm = [BookmarkManager sharedManager];
path = [bundle pathForResource: @"Defaults" ofType: @"plist"];
dict = [NSDictionary dictionaryWithContentsOfFile: path];
@ -39,14 +55,17 @@
[[NSUserDefaults standardUserDefaults] registerDefaults: dict];
}
_diskImages = [DiskImagesWindowController sharedInstance]; //[DiskImagesWindowController new];
if ([self installMameComponents]) {
[self displayLaunchWindow];
}
}
-(void)displayLaunchWindow {
if (!_launcher) {
@ -69,12 +88,21 @@
NSDate *newDate = [defaults objectForKey: kMameComponentsDate];
if (![newDate isKindOfClass: [NSDate class]])
newDate = nil;
if (!newDate) return YES; //????
if (oldDate && [oldDate compare: newDate] >= 0) return YES;
#if 0
NSString *path = [bundle pathForResource: @"mame-data" ofType: @"tgz"];
if (!path) return YES; // Ample Lite?
#endif
NSString *ssp = [bundle sharedSupportPath];
NSString *path = [ssp stringByAppendingPathComponent: @"mame-data.tgz"];
if (![[NSFileManager defaultManager] fileExistsAtPath: path])
return YES; // Ample Lite?
NSWindow *win = _installWindow;
@ -84,18 +112,23 @@
@"xfz",
path
];
[task setExecutableURL: [NSURL fileURLWithPath: @"/usr/bin/tar"]];
if (@available(macOS 10.13, *)) {
[task setExecutableURL: [NSURL fileURLWithPath: @"/usr/bin/tar"]];
[task setCurrentDirectoryURL: sd];
} else {
[task setLaunchPath: @"/usr/bin/tar"];
[task setCurrentDirectoryPath: SupportDirectoryPath()];
}
[task setArguments: argv];
[task setCurrentDirectoryURL: sd];
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC));
[task setTerminationHandler: ^(NSTask *task){
int st = [task terminationStatus];
// delay so the install window is visible, I think
dispatch_after(when, dispatch_get_main_queue(), ^{
int st = [task terminationStatus];
if (st) {
NSAlert *alert = [NSAlert new];
[alert setMessageText: @"An error occurred extracting MAME components"];
@ -112,6 +145,7 @@
}
[win close];
[self displayLaunchWindow];
[self displayROMS: nil];
});
}];
@ -123,6 +157,7 @@
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
@ -130,6 +165,18 @@
}
-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
NSString *ext = [[filename pathExtension] lowercaseString];
if ([ext isEqualToString: @"vgm"] || [ext isEqualToString: @"vgz"]) {
// run mame...
NSArray *args = @[ @"vgmplay", @"-window", @"-nomax", @"-skip_gameinfo", @"-quik", filename ];
[LogWindowController controllerForArgs: args];
}
return NO;
}
#pragma mark - IBActions
@ -143,12 +190,127 @@
}
- (IBAction)downloadROMS:(id)sender {
- (IBAction)displayROMS:(id)sender {
if (!_downloader) {
_downloader = [DownloadWindowController new];
_downloader = [DownloadWindowController sharedInstance];
}
[_downloader showWindow: sender];
}
- (IBAction)displayRecentDiskImages:(id)sender {
if (!_diskImages) {
_diskImages = [DiskImagesWindowController sharedInstance];
}
[_diskImages showWindow: sender];
}
- (IBAction)displayCheatSheet:(id)sender {
if (!_cheatSheet) {
_cheatSheet = [CheatSheetWindowController new];
}
[_cheatSheet showWindow: sender];
}
- (IBAction)displaySupportDirectory:(id)sender {
NSURL *url = SupportDirectory();
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws openURL: url];
}
- (IBAction)mameDocumentation:(id)sender {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSURL *url = [NSURL URLWithString: @"https://docs.mamedev.org"];
[ws openURL: url];
}
- (IBAction)mameAppleWiki:(id)sender {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSURL *url = [NSURL URLWithString: @"https://wiki.mamedev.org/index.php/Driver:Apple_II"];
[ws openURL: url];
}
- (IBAction)mameMac68kWiki:(id)sender {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSURL *url = [NSURL URLWithString: @"https://wiki.mamedev.org/index.php/Driver:Mac_68K"];
[ws openURL: url];
}
- (IBAction)manageBookmarks: (id)sender {
if (!_bookmarks) {
_bookmarks = [BookmarkWindowController new];
}
[_bookmarks showWindow: sender];
}
-(IBAction)installMameComponents:(id)sender {
/* install the mame data components. */
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSBundle *bundle = [NSBundle mainBundle];
NSURL *sd = SupportDirectory();
NSURL *ample_url = [sd URLByAppendingPathComponent: @"Ample.plist"];
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithContentsOfURL: ample_url];
//NSDate *oldDate = [d objectForKey: kMameComponentsDate];
NSDate *newDate = [defaults objectForKey: kMameComponentsDate];
if (![newDate isKindOfClass: [NSDate class]])
newDate = nil;
NSString *path = [bundle pathForResource: @"mame-data" ofType: @"tgz"];
if (!path) return; // Ample Lite?
NSWindow *win = _installWindow;
[win makeKeyAndOrderFront: nil];
NSTask *task = [NSTask new];
NSArray *argv = @[
@"xfz",
path
];
if (@available(macOS 10.13, *)) {
[task setExecutableURL: [NSURL fileURLWithPath: @"/usr/bin/tar"]];
[task setCurrentDirectoryURL: sd];
} else {
[task setLaunchPath: @"/usr/bin/tar"];
[task setCurrentDirectoryPath: SupportDirectoryPath()];
}
[task setArguments: argv];
//dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC));
[task setTerminationHandler: ^(NSTask *task){
int st = [task terminationStatus];
dispatch_async(dispatch_get_main_queue(), ^{
if (st) {
NSAlert *alert = [NSAlert new];
[alert setMessageText: @"An error occurred extracting MAME components"];
[alert runModal];
[win close];
return;
}
if (d) {
[d setObject: newDate forKey: kMameComponentsDate];
[d writeToURL: ample_url atomically: YES];
} else {
[@{ kMameComponentsDate: newDate } writeToURL: ample_url atomically: YES];
}
[win close];
// need to reload the software list data.
});
}];
[task launch];
}
@end

View File

@ -1,53 +1,63 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"idiom" : "mac",
"filename" : "icon-16.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"idiom" : "mac",
"filename" : "icon-32.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"idiom" : "mac",
"filename" : "icon-32.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"idiom" : "mac",
"filename" : "icon-64.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon-128.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon-256.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"idiom" : "mac",
"filename" : "icon-256.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"idiom" : "mac",
"filename" : "icon-512.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"idiom" : "mac",
"filename" : "icon-512.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"idiom" : "mac",
"filename" : "icon-1024.png",
"scale" : "2x"
}
],

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -0,0 +1,42 @@
//
// AutocompleteControl.h
// Autocomplete
//
// Created by Kelvin Sherlock on 2/20/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@class AutocompleteControl;
@protocol AutocompleteItem
-(NSString *)menuTitle;
-(NSAttributedString *)menuAttributedTitle; //?? can it still handle color?
-(BOOL)menuEnabled;
-(BOOL)menuIsHeader;
@end
@protocol AutoCompleteDelegate
-(NSArray<id<AutocompleteItem>> *)autocomplete: (AutocompleteControl *)control completionsForString: (NSString *)string;
-(NSArray<id<AutocompleteItem>> *)autocomplete: (AutocompleteControl *)control completionsForItem: (id<AutocompleteItem>)item;
@end
@interface AutocompleteControl : NSSearchField
@property NSInteger minWidth;
@property NSInteger maxDisplayItems;
@property (nullable, weak) id<AutoCompleteDelegate> autocompleteDelegate;
-(void)invalidate;
@end
NS_ASSUME_NONNULL_END

885
Ample/AutocompleteControl.m Normal file
View File

@ -0,0 +1,885 @@
//
// AutocompleteControl.m
// Autocomplete
//
// Created by Kelvin Sherlock on 2/20/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import "AutocompleteControl.h"
#include <wctype.h>
/*
Todo --
- when there is a value, can filter the list by only including header items and the selected value
- draw inactive menu items
- when menu is hidden then text is manually deleted (not esc canceled), then down/up arrow the list needs to update.
- eliminate nib and do it manually.
- when menus is too tall, macos moves it to the top of the screen.
- 1. it's not moved someplace more appropriate when the size shrinks
- 2. it should display to the left or right in that case.
- need to know parent's frame.
- fuzzy search - minimum distance between letters?
*/
@interface ACMenuView : NSView
@property (nonatomic) NSArray<id<AutocompleteItem>> *items;
@property (weak) AutocompleteControl *parent;
-(void)reset;
-(void)reset: (id<AutocompleteItem>)value;
-(void)setItems:(NSArray<id<AutocompleteItem>> *)items;
-(void)setItems:(NSArray<id<AutocompleteItem>> *)items value: (id<AutocompleteItem>)value;
@end
@interface AutocompleteControl ()
{
IBOutlet NSPanel *_panel;
__weak IBOutlet ACMenuView *_menuView;
__weak IBOutlet NSScrollView *_scrollView;
id<AutocompleteItem> _value;
BOOL _editing;
BOOL _dirty;
}
@end
@interface AutocompleteControl (SearchField) <NSSearchFieldDelegate>
-(void)fixTextColor: (BOOL)editing;
@end
@implementation AutocompleteControl
-(void)_init {
[self setDelegate: self];
[self setPlaceholderString: @""];
[(NSSearchFieldCell *)[self cell] setSearchButtonCell: nil];
NSBundle *bundle = [NSBundle mainBundle];
NSNib *nib = [[NSNib alloc] initWithNibNamed: @"Autocomplete" bundle: bundle];
NSArray *topLevel = nil;
[nib instantiateWithOwner: self topLevelObjects: &topLevel];
[_panel setMovable: NO];
[_panel setBecomesKeyOnlyIfNeeded: YES];
[_menuView setParent: self];
}
-(id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame: frameRect])) {
[self _init];
}
return self;
}
-(id)initWithCoder:(NSCoder *)coder {
if ((self = [super initWithCoder: coder])) {
[self _init];
}
return self;
}
#if 0
-(NSString *)stringValue {
return [super stringValue];
}
#endif
-(id)objectValue {
return _value;
}
-(void)setStringValue:(NSString *)stringValue {
[super setStringValue: stringValue ? stringValue : @""];
if (_value && [[_value menuTitle] isEqualToString: stringValue] == NO) {
// post change notification?
_value = nil;
[_menuView reset];
}
[self fixTextColor: _editing];
// todo -- search for a matching item, update text color.
}
// todo -- _menuView has second copy of value, need to update that.
-(void)setObjectValue:(id)objectValue {
if (_value == objectValue) return;
if (![objectValue conformsToProtocol: @protocol(AutocompleteItem)]) {
_value = nil;
[_menuView reset];
[super setStringValue: @""];
[self fixTextColor: _editing];
return;
}
_value = objectValue;
if (!_value) [super setStringValue: @""]; //
else {
[super setStringValue: [_value menuTitle]];
[_menuView reset: _value];
// TODO -- menu view currently uses text search.
//NSArray *array = [_autocompleteDelegate autocomplete: self completionsForItem: _value];
//[_menuView setItems: array value: _value];
}
[self fixTextColor: NO];
}
-(BOOL)valid {
return _value != nil;
}
-(void)hideSuggestions: (id)sender {
if (![_panel isVisible]) return;
NSWindow *window = [self window];
[window removeChildWindow: _panel];
[_panel orderOut: sender];
}
-(void)showSuggestions: (id)sender {
if ([_panel isVisible]) return;
NSWindow *window = [self window];
NSRect wFrame = [_panel frame];
NSRect vFrame = [self frame];
NSRect rect = { .origin = vFrame.origin, .size = wFrame.size };
rect = [window convertRectToScreen:rect];
rect.origin.y -= wFrame.size.height + 4;
rect.size.width = MAX(vFrame.size.width, _minWidth);
// todo - min width option.
[_panel setFrame: rect display: YES];
//[_panel setFrameOrigin: rect.origin];
[window addChildWindow: _panel ordered: NSWindowAbove];
}
-(void)updateSuggestions {
if (!_autocompleteDelegate) return;
NSString *needle = [self stringValue];
NSArray *items = [_autocompleteDelegate autocomplete: self completionsForString: needle];
[_menuView setItems: items];
if ([items count]) {
[self showSuggestions: nil];
} else {
[self hideSuggestions: nil];
}
}
-(void)invalidate {
if (!_autocompleteDelegate) return;
NSArray *items = nil;
/* if there is an object value, try to retain it. */
if (_value) {
[_menuView reset];
items = [_autocompleteDelegate autocomplete: self completionsForItem: _value];
if (items) {
[_menuView setItems: items];
return;
}
_value = nil;
[self invoke];
}
NSString *needle = [self stringValue];
if ([needle length]) {
_dirty = YES;
}
// if only 1 match, auto-set value?
items = [_autocompleteDelegate autocomplete: self completionsForString: needle];
[self fixTextColor: _editing];
[_menuView setItems: items];
}
// prevent action messages from the search field/cell.
-(BOOL)sendAction:(SEL)action to:(id)target {
if (action == [self action] && target == [self target]) return NO;
return [super sendAction: action to: target];
}
-(void)invoke {
_dirty = NO;
[super sendAction: [self action] to: [self target]];
}
@end
@implementation AutocompleteControl (SearchField)
-(void)fixTextColor: (BOOL)editing {
NSColor *color = editing || _value ? [NSColor controlTextColor] : [NSColor systemRedColor];
[self setTextColor: color];
}
- (void)controlTextDidChange:(NSNotification *)notification {
//NSLog(@"controlTextDidChange");
if (_value) {
_dirty = YES;
_value = nil;
}
NSString *s = [self stringValue];
if ([s length]) {
[self updateSuggestions];
} else {
_dirty = YES;
_value = nil;
[_menuView reset];
[_menuView setItems: nil];
[self hideSuggestions: nil];
[self invoke];
}
}
- (void)controlTextDidBeginEditing:(NSNotification *)obj {
//NSLog(@"controlTextDidBeginEditing");
_editing = YES;
_dirty = NO;
[self fixTextColor: YES];
}
- (void)controlTextDidEndEditing:(NSNotification *)obj {
//NSLog(@"controlTextDidEndEditing");
_editing = NO;
[self hideSuggestions: nil];
if (_dirty) {
_value = nil;
[self invoke];
}
[self fixTextColor: NO];
}
-(BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor {
return YES;
}
-(BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor {
return YES;
}
-(void)selectItem:(id<AutocompleteItem>)item withSelector:(SEL)selector {
// for newline/mousedown, will still retain focus after updating
// so we need to invalidate the value if it's edited further.
if (selector == @selector(insertNewline:) || selector == @selector(mouseDown:) || selector == @selector(insertTab:)) {
_value = item;
NSString *str = [item menuTitle];
[super setStringValue: str];
[self hideSuggestions: nil];
NSText *fieldEditor = [self currentEditor];
//[fieldEditor setSelectedRange: NSMakeRange([str length], 0)];
[fieldEditor setSelectedRange: NSMakeRange(0, [str length])];
[self invoke];
// need to invalidate the menu so it reloads
#if 0
NSArray *array = [_autocompleteDelegate autocomplete: self completionsForItem: _value];
[_menuView setItems: array];
#else
[_menuView setItems: nil];
#endif
//NSLog(@"selectItem:withSelector:");
}
}
- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
if (commandSelector == @selector(moveUp:)) {
//[self showSuggestions: nil];
if ([_panel isVisible]) {
[_menuView moveUp: textView];
} else {
[self updateSuggestions];
}
return YES;
}
if (commandSelector == @selector(moveDown:)) {
//[self showSuggestions: nil];
if ([_panel isVisible]) {
[_menuView moveDown: textView];
} else {
[self updateSuggestions];
}
return YES;
}
if (commandSelector == @selector(insertNewline:)) {
if ([_panel isVisible])
[_menuView insertNewline: textView];
return YES;
}
if (commandSelector == @selector(insertTab:)) {
if ([_panel isVisible])
[_menuView insertTab: textView];
return NO;
}
if (commandSelector == @selector(complete:)) {
if ([_panel isVisible]) {
[self hideSuggestions: nil];
} else {
[self updateSuggestions];
}
return YES;
}
// esc ?
// if panel open, hide
// if panel closed, delete.
if (commandSelector == @selector(cancelOperation:)) {
if ([_panel isVisible]) {
[self hideSuggestions: nil];
} else {
_value = nil;
[super setStringValue: @""];
[self hideSuggestions: nil];
[_menuView reset];
//[_menuView setItems: _completions];
// sigh...
#if 0
NSArray *items =[_autocompleteDelegate autocomplete: self completionsForString: @""];
[_menuView setItems: items];
#endif
[self invoke];
}
return YES;
}
if (commandSelector == @selector(scrollPageDown:)) {
if ([_panel isVisible]) {
[_menuView scrollPageDown: textView];
} else {
[self updateSuggestions];
}
return YES;
}
if (commandSelector == @selector(scrollPageUp:)) {
if ([_panel isVisible]) {
[_menuView scrollPageUp: textView];
} else {
[self updateSuggestions];
}
return YES;
}
//NSLog(@"%@", NSStringFromSelector(commandSelector));
return NO;
}
@end
@interface ACMenuView () {
id<AutocompleteItem> _value;
NSInteger _index;
NSInteger _count;
NSArray<id<AutocompleteItem>> *_items;
NSTrackingArea *_trackingArea;
NSColor *_backgroundColor;
NSColor *_selectedColor;
BOOL _tracking;
BOOL _clipped;
}
@end
@implementation ACMenuView
#define MENU_FONT_SIZE 11
#define MENU_HEIGHT 14
#define MARGIN_TOP 0 //6
#define MARGIN_BOTTOM 0 //6
#define INDENT 7
#define HEADER_INDENT 7
#define MAX_DISPLAY_ITEMS 16
-(void)_init {
_backgroundColor = [NSColor windowBackgroundColor];
if (@available(macOS 10.14, *)) {
_selectedColor = [NSColor selectedContentBackgroundColor];
} else {
_selectedColor = [NSColor selectedTextBackgroundColor];
}
NSTrackingAreaOptions options = NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect | NSTrackingActiveInActiveApp;
_trackingArea = [[NSTrackingArea alloc] initWithRect: NSZeroRect
options: options
owner: self
userInfo: nil];
[self addTrackingArea: _trackingArea];
}
-(id)initWithCoder:(NSCoder *)coder {
if ((self = [super initWithCoder: coder])) {
[self _init];
}
return self;
}
-(BOOL)isFlipped {
return YES;
}
-(BOOL)acceptsFirstMouse:(NSEvent *)event {
return YES;
}
static CGFloat HeightForItems(NSUInteger count) {
return count * MENU_HEIGHT;
}
-(NSSize)intrinsicContentSize {
return NSMakeSize(NSViewNoIntrinsicMetric, _count * MENU_HEIGHT + MARGIN_TOP + MARGIN_BOTTOM);
}
- (NSSize)sizeThatFits:(NSSize)size {
size.height = _count * MENU_HEIGHT + MARGIN_TOP + MARGIN_BOTTOM;
return size;
}
- (void)sizeToFit {
NSSize size = [self frame].size;
size.height = _count * MENU_HEIGHT + MARGIN_TOP + MARGIN_BOTTOM;
[self setFrameSize: size];
[self setNeedsDisplay: YES];
}
-(void)reset {
[self invalidateRow: _index];
_index = -1;
_value = nil;
_items = nil;
}
-(void)reset: (id<AutocompleteItem>)value {
[self invalidateRow: _index];
_index = -1;
_items = nil;
_value = value;
}
-(void)setItems:(NSArray *)items value: (id<AutocompleteItem> )value {
if (_items == items && _value == value) return;
_items = [items copy];
_index = -1;
_count = [items count];
_value = value;
if (!_items) {
_value = nil;
return;
}
// also check enabled status....
if (_value) {
_index = [_items indexOfObject: _value];
if (_index == NSNotFound) {
_index = -1;
_value = nil;
}
}
// if only 1 entry, auto-select it.
if (!_value) {
NSInteger count = -1;
for (id<AutocompleteItem> item in _items) {
++count;
if ([item menuIsHeader]) continue;
if (_value) {
_value = nil;
_index = -1;
break;
}
_value = item;
_index = count;
}
}
NSInteger displayCount = MIN(_count, MAX_DISPLAY_ITEMS);
CGFloat newHeight = HeightForItems(displayCount) + 8 ; // 4px top/bottom
NSWindow *window = [self window];
NSRect wFrame = [window frame];
NSRect contentRect = [[[self enclosingScrollView] contentView] frame];
//NSSize size = [self intrinsicContentSize];
//NSInteger minWidth = [_parent minWidth];
//size.width = MAX(wFrame.size.width, minWidth);
//size.height += 8;
CGFloat delta = wFrame.size.height - newHeight;
wFrame.origin.y += delta;
wFrame.size.height = newHeight;
_clipped = (_count > displayCount);
[self setFrameSize: NSMakeSize(contentRect.size.width /*- 15.0*/, HeightForItems(_count))];
[self setNeedsDisplay: YES];
[window setFrame: wFrame display: YES];
if (_value) {
[self scrollToRow: _index position: ScrollToCenter force: NO];
} else {
[self scrollToRow: 0 position: ScrollToTop force: YES];
}
//[self sizeToFit];
//[[self window] setContentSize: [self frame].size];
//NSLog(@"%@", NSStringFromRect(wFrame));
}
-(void)setItems:(NSArray<id<AutocompleteItem>> *)items {
if (_items == items) return;
[self setItems: items value: _value];
}
-(id<AutocompleteItem>)itemAtPoint: (NSPoint)point indexPtr: (NSInteger *)indexPtr {
NSInteger index = floor(point.y / MENU_HEIGHT);
if (index < 0 || index >= _count) return nil;
if (indexPtr) *indexPtr = index;
return [_items objectAtIndex: index];
}
enum {
ScrollToTop,
ScrollToBottom,
ScrollToCenter,
};
-(void)scrollToRow: (NSInteger)row position: (unsigned)position force: (BOOL)force {
if (row < 0) return;
if (!_clipped) return;
NSScrollView *scrollView = [self enclosingScrollView];
NSClipView *clipView = [scrollView contentView];
NSRect visibleRect = [self visibleRect];
if (!force) {
NSRect mRect = NSMakeRect(0, row * MENU_HEIGHT, 1 , MENU_HEIGHT);
if (NSContainsRect(visibleRect, mRect)) return;
}
NSInteger topRow = row;
switch (position) {
case ScrollToTop:
break;
case ScrollToBottom:
topRow -= MAX_DISPLAY_ITEMS -1;
break;
case ScrollToCenter:
topRow -= MAX_DISPLAY_ITEMS/2 - 1;
break;
}
if (topRow < 0) topRow = 0;
if (topRow > _count - MAX_DISPLAY_ITEMS)
topRow = _count - MAX_DISPLAY_ITEMS;
NSPoint point = NSMakePoint(0, topRow * MENU_HEIGHT);
//[self scrollClipView: clipView toPoint: point];
[clipView scrollToPoint: point];
[scrollView reflectScrolledClipView: clipView];
}
-(void)moveUp:(id)sender {
if (_count == 0 || _index <= 0) return;
NSInteger index = 0;
id<AutocompleteItem> value = nil;
for (index = _index - 1; index >= 0; --index) {
value = [_items objectAtIndex: index];
if ([value menuIsHeader]) continue;
if (![value menuEnabled]) continue;
break;
}
if (index < 0) return;
if (index == _index) return;
[self invalidateRow: _index];
[self invalidateRow: index];
_index = index;
_value = value;
[self scrollToRow: index position: ScrollToTop force: NO];
[_parent selectItem: _value withSelector: _cmd];
}
-(void)moveDown:(id)sender {
// _index -1 selects first item.
if (_count == 0 || _index == _count - 1) return;
NSInteger index = 0;
id<AutocompleteItem> value = nil;
for (index = _index + 1; index < _count ; ++index) {
value = [_items objectAtIndex: index];
if ([value menuIsHeader]) continue;
if (![value menuEnabled]) continue;
break;
}
if (index == _count) return;
if (index == _index) return;
[self invalidateRow: _index];
[self invalidateRow: index];
_index = index;
_value = value;
[self scrollToRow: index position: ScrollToBottom force: NO];
[_parent selectItem: _value withSelector: _cmd];
}
-(void)scrollPageUp:(id)sender {
if (_count == 0 || _index <= 0) return;
}
-(void)scrollPageDown:(id)sender {
if (_count == 0 || _index == _count - 1) return;
}
-(void)insertNewline:(id)sender {
if (_value) {
[_parent selectItem: _value withSelector: _cmd];
}
}
-(void)insertTab:(id)sender {
// if only one option, autocomplete?
if (_value) {
[_parent selectItem: _value withSelector: _cmd];
}
}
-(void)mouseMoved:(NSEvent *)event {
//NSLog(@"mouse moved");
if (!_tracking) return;
NSPoint p = [event locationInWindow];
p = [self convertPoint: p fromView: nil];
NSInteger index;
id<AutocompleteItem> value = [self itemAtPoint: p indexPtr: &index];
if (!value) return;
if (index == _index) return;
if ([value menuIsHeader]) return;
if (![value menuEnabled]) return;
[self invalidateRow: _index];
[self invalidateRow: index];
_index = index;
_value = value;
[_parent selectItem: _value withSelector: _cmd];
}
-(void)mouseDown:(NSEvent *)event {
if (!_tracking) return;
NSPoint p = [event locationInWindow];
p = [self convertPoint: p fromView: nil];
NSInteger index;
id<AutocompleteItem> value = [self itemAtPoint: p indexPtr: &index];
if (!value) return;
if (index != _index) {
if ([value menuIsHeader]) return;
if (![value menuEnabled]) return;
[self invalidateRow: _index];
[self invalidateRow: index];
_index = index;
_value = value;
}
[_parent selectItem: _value withSelector: _cmd];
}
-(void)mouseEntered:(NSEvent *)event {
//NSLog(@"mouse entered");
_tracking = YES;
}
-(void)mouseExited:(NSEvent *)event {
//NSLog(@"mouse exited");
_tracking = NO;
}
-(void)invalidateRow:(NSInteger)row {
if (row < 0 || row >= _count) return;
NSRect r = NSZeroRect;
NSRect bounds = [self bounds];
r.size.width = bounds.size.width;
r.size.height = MENU_HEIGHT;
r.origin.y = MENU_HEIGHT * row + MARGIN_TOP;
//NSLog(@"Invalidating %ld - %@", row, NSStringFromRect(r));
[self setNeedsDisplayInRect: r];
}
static void DrawString(NSString *str, NSDictionary *attr, CGRect rect) {
NSSize size = [str sizeWithAttributes: attr];
if (size.width <= rect.size.width) {
[str drawInRect: rect withAttributes: attr];
return;
}
NSMutableString *mstr = [str mutableCopy];
// binary search is probably the best way to handle it :/
NSInteger l = [mstr length];
while (l > 2) {
[mstr replaceCharactersInRange: NSMakeRange(l-2, 2) withString: @"…"];
--l;
size = [mstr sizeWithAttributes: attr];
if (size.width <= rect.size.width) {
[mstr drawInRect: rect withAttributes: attr];
return;
}
}
}
-(void)drawItem: (id<AutocompleteItem>)item inRect: (NSRect)rect {
NSColor *textColor = [NSColor textColor];
if (!item) return;
if (item == _value) {
textColor = [NSColor selectedMenuItemTextColor];
[_selectedColor setFill];
NSRectFill(rect);
}
NSString *string = [item menuTitle];
if ([item menuIsHeader]) {
textColor = [NSColor secondaryLabelColor];
NSDictionary *attr = @{
NSForegroundColorAttributeName: textColor,
NSFontAttributeName: [NSFont systemFontOfSize: MENU_FONT_SIZE], // [NSFont boldSystemFontOfSize: 13],
};
NSRect r = NSInsetRect(rect, HEADER_INDENT, 0);
DrawString(string, attr, r);
} else {
NSDictionary *attr = @{
NSForegroundColorAttributeName: textColor,
NSFontAttributeName: [NSFont systemFontOfSize: MENU_FONT_SIZE],
};
NSRect r = NSInsetRect(rect, INDENT, 0);
r.origin.x += INDENT;
r.size.width -= INDENT;
DrawString(string, attr, r);
}
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
NSRect r = [self bounds];
NSInteger begin = floor((NSMinY(dirtyRect) - MARGIN_TOP) / MENU_HEIGHT);
NSInteger end = ceil((NSMaxY(dirtyRect) - MARGIN_TOP) / MENU_HEIGHT);
if (begin < 0) begin = 0;
if (end > _count) end = _count;
r.origin.y = MENU_HEIGHT * begin + MARGIN_TOP;
r.size.height = MENU_HEIGHT;
for (NSInteger index = begin; index < end; ++index) {
id<AutocompleteItem> item = [_items objectAtIndex: index];
[self drawItem: item inRect: r];
r.origin.y += MENU_HEIGHT;
}
}
@end
/* custom scroller that doesn't draw a background. */
@interface ACScroller : NSScroller
@end
@implementation ACScroller
-(void)drawRect:(NSRect)dirtyRect {
//[[NSColor windowBackgroundColor] set];
[[NSColor clearColor] set];
NSRectFill(dirtyRect);
[self drawKnob];
}
@end
@interface ACPanel : NSPanel
@end
@implementation ACPanel
/* needed to prevent the pop-up child window from being moved when offscreen. */
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen {
return frameRect;
}
@end

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="AutocompleteControl">
<connections>
<outlet property="_menuView" destination="F2h-9b-Ouu" id="min-gE-sma"/>
<outlet property="_panel" destination="OYW-cj-FD5" id="DYJ-rN-6Ep"/>
<outlet property="_scrollView" destination="VQ6-PE-hTH" id="iKA-Ps-nkl"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" titlebarAppearsTransparent="YES" titleVisibility="hidden" id="OYW-cj-FD5" customClass="ACPanel">
<windowStyleMask key="styleMask" utility="YES" nonactivatingPanel="YES" fullSizeContentView="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="272" y="172" width="300" height="400"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="3pz-HL-mV1">
<rect key="frame" x="0.0" y="0.0" width="300" height="400"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="0.0" horizontalPageScroll="0.0" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" id="VQ6-PE-hTH">
<rect key="frame" x="0.0" y="4" width="300" height="392"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="HWy-NN-aOV">
<rect key="frame" x="0.0" y="0.0" width="300" height="392"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view id="F2h-9b-Ouu" customClass="ACMenuView">
<rect key="frame" x="0.0" y="0.0" width="300" height="392"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</view>
</subviews>
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="Az6-1a-Hei">
<rect key="frame" x="-100" y="-100" width="168" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="tng-g2-1LZ" customClass="ACScroller">
<rect key="frame" x="285" y="0.0" width="15" height="392"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
</view>
<point key="canvasLocation" x="127" y="73"/>
</window>
</objects>
</document>

View File

@ -0,0 +1,223 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="BookmarkWindowController">
<connections>
<outlet property="arrayController" destination="7gA-MI-adT" id="XJ0-qj-ho5"/>
<outlet property="bookmarkManager" destination="Ryd-Nr-sPf" id="LM4-IP-ehb"/>
<outlet property="tableView" destination="mkQ-pQ-kXu" id="jqC-GF-vrE"/>
<outlet property="window" destination="QvC-M9-y7g" id="ovK-qY-XrZ"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Bookmarks" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="400" height="450"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="400" height="450"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cgh-jG-i97">
<rect key="frame" x="-1" y="-1" width="402" height="452"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" id="xDr-v4-sVR">
<rect key="frame" x="1" y="1" width="400" height="450"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" headerView="hmS-CB-Huq" viewBased="YES" id="mkQ-pQ-kXu">
<rect key="frame" x="0.0" y="0.0" width="400" height="425"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="232" minWidth="40" maxWidth="1000" id="U9x-dw-Kd3">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Name">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="jIY-mU-1gw">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<sortDescriptor key="sortDescriptorPrototype" selector="caseInsensitiveCompare:" sortKey="name"/>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="R8h-Wj-cHA">
<rect key="frame" x="1" y="1" width="237" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cIh-ya-lB0">
<rect key="frame" x="0.0" y="0.0" width="237" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" title="Table View Cell" id="a7b-vf-Kzd">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="R8h-Wj-cHA" name="value" keyPath="objectValue.name" id="UWc-85-Ghw">
<dictionary key="options">
<bool key="NSValidatesImmediately" value="YES"/>
</dictionary>
</binding>
</connections>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="cIh-ya-lB0" id="DMK-Kc-RpK"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn editable="NO" width="100" minWidth="100" maxWidth="100" id="fvh-YG-X9R">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Machine">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="waa-dh-M0V">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="machine"/>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="LUd-BZ-Kpw">
<rect key="frame" x="241" y="1" width="100" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4Qd-Zj-XZi">
<rect key="frame" x="0.0" y="0.0" width="100" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="ztJ-V1-N1t">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="LUd-BZ-Kpw" name="value" keyPath="objectValue.machine" id="IYK-LP-fHo"/>
</connections>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="4Qd-Zj-XZi" id="u3u-3q-Vc2"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn editable="NO" width="50" minWidth="50" maxWidth="50" id="rmr-1r-2Cb">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Default">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="zuw-8H-5ck">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="automatic"/>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="f3C-qX-bVY">
<rect key="frame" x="344" y="1" width="54" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LzD-ps-EdD">
<rect key="frame" x="19" y="1" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSStatusAvailable" id="kH7-IH-D1y"/>
<connections>
<binding destination="f3C-qX-bVY" name="hidden" keyPath="objectValue.automatic" id="izX-1f-EU8">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</imageView>
</subviews>
<connections>
<outlet property="imageView" destination="LzD-ps-EdD" id="hef-CI-Ly8"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<action trigger="doubleAction" selector="doubleClick:" target="-2" id="VaT-3X-cCf"/>
<binding destination="7gA-MI-adT" name="content" keyPath="arrangedObjects" id="5So-FR-r94"/>
<outlet property="dataSource" destination="-2" id="kso-yU-XdI"/>
<outlet property="delegate" destination="-2" id="Lyf-Wr-8w0"/>
<outlet property="menu" destination="cH2-L7-ScC" id="3MS-Tc-P04"/>
</connections>
</tableView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="O1o-6N-F5z">
<rect key="frame" x="-100" y="-100" width="223" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="3n8-lN-RGL">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" wantsLayer="YES" id="hmS-CB-Huq">
<rect key="frame" x="0.0" y="0.0" width="400" height="25"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
</subviews>
</view>
<connections>
<outlet property="delegate" destination="-2" id="4OM-KB-CAh"/>
</connections>
<point key="canvasLocation" x="-72" y="91"/>
</window>
<arrayController mode="entity" entityName="Bookmark" automaticallyPreparesContent="YES" preservesSelection="NO" selectsInsertedObjects="NO" avoidsEmptySelection="NO" clearsFilterPredicateOnInsertion="NO" id="7gA-MI-adT">
<connections>
<binding destination="Ryd-Nr-sPf" name="managedObjectContext" keyPath="managedObjectContext" id="hMi-JG-LQC"/>
<binding destination="-2" name="selectionIndexes" keyPath="tableView.selectedRowIndexes" id="dyb-Wv-Duo"/>
<binding destination="-2" name="sortDescriptors" keyPath="tableView.sortDescriptors" previousBinding="dyb-Wv-Duo" id="fkc-Yv-ZLN"/>
</connections>
</arrayController>
<customObject id="Ryd-Nr-sPf" customClass="BookmarkManagerProxy"/>
<menu id="cH2-L7-ScC">
<items>
<menuItem title="Set Default" id="JGR-HC-oCO">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="setDefault:" target="-2" id="QQK-aI-l2p"/>
</connections>
</menuItem>
<menuItem title="Clear Default" id="ulz-3z-Pgl">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="clearDefault:" target="-2" id="mIc-UM-kj0"/>
</connections>
</menuItem>
<menuItem title="Delete" id="B7V-fY-Cbe">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="deleteBookmark:" target="-2" id="zQl-vg-Eg4"/>
</connections>
</menuItem>
</items>
<connections>
<outlet property="delegate" destination="-2" id="raV-YO-2UW"/>
</connections>
<point key="canvasLocation" x="355" y="-28"/>
</menu>
</objects>
<resources>
<image name="NSStatusAvailable" width="16" height="16"/>
</resources>
</document>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="CheatSheetWindowController">
<connections>
<outlet property="window" destination="QvC-M9-y7g" id="U2v-sN-OzH"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Keyboard Cheat Sheet" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="196" y="240" width="640" height="640"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="640" height="640"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<connections>
<outlet property="delegate" destination="-2" id="u4H-aq-RE2"/>
</connections>
<point key="canvasLocation" x="42" y="198"/>
</window>
</objects>
</document>

View File

@ -1,14 +1,15 @@
{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600
{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;}
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;\cssrgb\c100000\c100000\c100000;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;\red38\green38\blue38;
}
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;\cssrgb\c100000\c100000\c100000;\cssrgb\c20000\c20000\c20000;
}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\b\fs36 \cf2 Ample\cf0
\f1\b0\fs28 would like to thank\'85\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\cf0 \
\
\pard\pardeftab720\qc\partightenfactor0
{\field{\*\fldinst{HYPERLINK "https://www.mamedev.org"}}{\fldrslt
\f0\b\fs36 \cf0 \cb3 \expnd0\expndtw0\kerning0
@ -30,4 +31,26 @@ Please note that MAME is a registered trademark of Gregory Ember, and permission
\cf0 \
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qj\partightenfactor0
\cf0 \cb1 \kerning1\expnd0\expndtw0 SDL 2.0 is distributed under the {\field{\*\fldinst{HYPERLINK "https://libsdl.org/license.php"}}{\fldrslt zlib license}}. This license allows you to use SDL freely in any software.\
}
\
\pard\pardeftab720\qc\partightenfactor0
{\field{\*\fldinst{HYPERLINK "https://sparkle-project.org/"}}{\fldrslt
\f0\b\fs36 \cf0 \cb3 \expnd0\expndtw0\kerning0
Sparkle}}\
\pard\pardeftab720\partightenfactor0
\cf0 \
Sparkle is open source software available under the permissive MIT license, and is developed on GitHub by the Sparkle Project with the help of dozens of valued contributors.\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\partightenfactor0
\cf0 \
\pard\pardeftab720\qc\partightenfactor0
{\field{\*\fldinst{HYPERLINK "https://usdawatercolors.nal.usda.gov/pom/catalog.xhtml?id=POM00001916"}}{\fldrslt
\f0\b\fs36 \cf0 \cb3 \expnd0\expndtw0\kerning0
Icon}}
\f0\b\fs36 \cb3 \expnd0\expndtw0\kerning0
\
\pard\pardeftab720\qj\partightenfactor0
\f1\b0\fs28 \cf0 \
\pard\pardeftab720\qj\partightenfactor0
\cf4 R.C. Steadman, 1921-06-01.\
\
U.S. Department of Agriculture Pomological Watercolor Collection. Rare and Special Collections, National Agricultural Library, Beltsville, MD 20705}

View File

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="DiskImagesWindowController">
<connections>
<outlet property="arrayController" destination="YmL-8S-msS" id="Pva-sz-XFI"/>
<outlet property="tableView" destination="cqO-ig-A9t" id="hbI-ho-WYj"/>
<outlet property="window" destination="AtY-lA-KIp" id="aaq-cR-kq8"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customObject id="stE-9g-lJ2" customClass="BookmarkManagerProxy"/>
<arrayController mode="entity" entityName="DiskImage" automaticallyPreparesContent="YES" avoidsEmptySelection="NO" automaticallyRearrangesObjects="YES" id="YmL-8S-msS">
<connections>
<binding destination="stE-9g-lJ2" name="managedObjectContext" keyPath="managedObjectContext" id="GyD-kH-DBa"/>
</connections>
</arrayController>
<menu id="bCS-1z-UOZ">
<items>
<menuItem title="Show in Finder" tag="1" id="roc-SG-geJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showInFinder:" target="-2" id="ViY-7R-MNV"/>
</connections>
</menuItem>
<menuItem title="Eject" tag="2" id="eJ1-Kd-hnR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="eject:" target="-2" id="c6U-xB-EnM"/>
</connections>
</menuItem>
</items>
<connections>
<outlet property="delegate" destination="-2" id="22a-3e-eaK"/>
</connections>
<point key="canvasLocation" x="-667" y="170"/>
</menu>
<window title="Recent Disk Images" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="RecentDiskImagesWindow" animationBehavior="default" id="AtY-lA-KIp">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="283" y="305" width="408" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
<view key="contentView" id="zHI-2R-bOe">
<rect key="frame" x="0.0" y="0.0" width="408" height="270"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="a3G-Wf-K8I">
<rect key="frame" x="-1" y="-1" width="410" height="272"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" id="SFr-s6-6di">
<rect key="frame" x="1" y="1" width="408" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" headerView="iwP-JL-O3g" viewBased="YES" id="cqO-ig-A9t">
<rect key="frame" x="0.0" y="0.0" width="408" height="245"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="300" minWidth="40" maxWidth="1000" id="k9E-Si-iTY">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Name">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="trJ-af-d0b">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<sortDescriptor key="sortDescriptorPrototype" selector="caseInsensitiveCompare:" sortKey="name"/>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="2Ic-UI-Je3">
<rect key="frame" x="1" y="1" width="305" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gkM-KB-x76">
<rect key="frame" x="0.0" y="0.0" width="305" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="PitchDark.2mg" id="Wcg-zo-CeN">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="2Ic-UI-Je3" name="value" keyPath="objectValue.name" id="FAu-HR-0jF"/>
<binding destination="2Ic-UI-Je3" name="toolTip" keyPath="objectValue.path" id="0MM-sv-mET"/>
</connections>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="gkM-KB-x76" id="tpG-TS-sXI"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn width="93" minWidth="40" maxWidth="1000" id="0aJ-xJ-YSS">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Size">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="jRd-9Y-U6W">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="size"/>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="UW9-AF-U9F">
<rect key="frame" x="309" y="1" width="97" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6Ry-Zn-euh">
<rect key="frame" x="0.0" y="0.0" width="97" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="32 MB" id="fXp-OZ-Qcu">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="UW9-AF-U9F" name="value" keyPath="objectValue.size" id="Hca-7L-QN7">
<dictionary key="options">
<string key="NSValueTransformerName">FileSizeTransformer</string>
</dictionary>
</binding>
</connections>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="6Ry-Zn-euh" id="vUm-0h-5qV"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<action trigger="doubleAction" selector="doubleClick:" target="-2" id="wdp-Ek-Olo"/>
<binding destination="YmL-8S-msS" name="content" keyPath="arrangedObjects" id="v56-YR-Qve"/>
<binding destination="YmL-8S-msS" name="sortDescriptors" keyPath="sortDescriptors" previousBinding="v56-YR-Qve" id="BGa-9c-RdD"/>
<outlet property="dataSource" destination="-2" id="gCn-sa-fuX"/>
<outlet property="delegate" destination="-2" id="VHT-aS-4iS"/>
<outlet property="menu" destination="bCS-1z-UOZ" id="a2u-hd-hPS"/>
</connections>
</tableView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="Z7O-AK-X5q">
<rect key="frame" x="1" y="119" width="223" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="OLa-ra-vIN">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" id="iwP-JL-O3g">
<rect key="frame" x="0.0" y="0.0" width="408" height="25"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
</subviews>
</view>
<toolbar key="toolbar" implicitIdentifier="D9701924-6955-47B8-A2FF-DBD466AAEB92" autosavesConfiguration="NO" allowsUserCustomization="NO" displayMode="iconOnly" sizeMode="regular" id="Gp6-Kl-lr2">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="lBE-ee-rCy"/>
<toolbarItem implicitItemIdentifier="C346E56F-4480-4D8A-8485-33A3A51D7B78" label="" paletteLabel="Filter" sizingBehavior="auto" id="DsU-uu-UmZ">
<nil key="toolTip"/>
<searchField key="view" wantsLayer="YES" verticalHuggingPriority="750" textCompletion="NO" id="qHV-IA-ysc">
<rect key="frame" x="0.0" y="14" width="96" height="22"/>
<autoresizingMask key="autoresizingMask"/>
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" continuous="YES" borderStyle="bezel" placeholderString="Filter" usesSingleLineMode="YES" bezelStyle="round" id="BWo-eC-ahz">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</searchFieldCell>
<connections>
<action selector="filter:" target="-2" id="KhW-DS-b8s"/>
</connections>
</searchField>
</toolbarItem>
</allowedToolbarItems>
<defaultToolbarItems>
<toolbarItem reference="lBE-ee-rCy"/>
<toolbarItem reference="lBE-ee-rCy"/>
<toolbarItem reference="DsU-uu-UmZ"/>
</defaultToolbarItems>
</toolbar>
<point key="canvasLocation" x="-196" y="513"/>
</window>
</objects>
</document>

View File

@ -8,53 +8,42 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="DownloadWindowController">
<connections>
<outlet property="allFilterButton" destination="Kgj-LP-FsF" id="yub-s9-RVW"/>
<outlet property="arrayController" destination="jhO-4z-Qwt" id="GHu-xb-4zU"/>
<outlet property="downloadField" destination="sJz-So-jbA" id="WjK-48-FcE"/>
<outlet property="formatButton" destination="2Rg-eX-DUq" id="oYo-MG-Sc6"/>
<outlet property="missingFilterButton" destination="6c7-tU-3F3" id="89Y-wQ-9pB"/>
<outlet property="tableView" destination="FLX-Wt-y53" id="a4O-pk-EAt"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="ROMs" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
<window title="ROMs" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="DownloadManagerWindow" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="196" y="240" width="400" height="500"/>
<rect key="contentRect" x="196" y="240" width="454" height="575"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<value key="minSize" type="size" width="300" height="300"/>
<value key="minSize" type="size" width="454" height="300"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="400" height="500"/>
<autoresizingMask key="autoresizingMask"/>
<rect key="frame" x="0.0" y="0.0" width="454" height="575"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rg5-Qf-4Mw">
<rect key="frame" x="324" y="19" width="56" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="roundTextured" title="Cancel" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="i6Z-OM-lqE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent">.</string>
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
<connections>
<binding destination="-2" name="enabled" keyPath="self.active" id="mBP-8S-yGB"/>
</connections>
</buttonCell>
<connections>
<action selector="cancelAll:" target="-2" id="ycl-eJ-ByB"/>
</connections>
</button>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CMD-nT-mEa">
<rect key="frame" x="0.0" y="58" width="402" height="443"/>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="51" horizontalPageScroll="10" verticalLineScroll="51" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CMD-nT-mEa">
<rect key="frame" x="0.0" y="130" width="456" height="446"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" id="Igp-aH-flp">
<rect key="frame" x="1" y="1" width="400" height="441"/>
<rect key="frame" x="1" y="1" width="454" height="444"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" ambiguous="YES" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" viewBased="YES" id="FLX-Wt-y53">
<rect key="frame" x="0.0" y="0.0" width="400" height="441"/>
<tableView verticalHuggingPriority="750" ambiguous="YES" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="49" rowSizeStyle="automatic" viewBased="YES" id="FLX-Wt-y53">
<rect key="frame" x="0.0" y="0.0" width="454" height="444"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<tableViewGridLines key="gridStyleMask" dashed="YES"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="397" minWidth="40" maxWidth="1000" id="5jP-bY-fhI">
<tableColumn width="451" minWidth="40" maxWidth="1000" id="5jP-bY-fhI">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
@ -67,63 +56,69 @@
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews>
<tableCellView identifier="Cell" focusRingType="none" id="aBv-F5-XWo">
<rect key="frame" x="1" y="1" width="397" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pWm-hb-BXB">
<rect key="frame" x="0.0" y="0.0" width="397" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="p71-gJ-vFV">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="pWm-hb-BXB" id="NNG-rj-AAQ"/>
</connections>
</tableCellView>
<tableCellView identifier="DownloadCell" focusRingType="none" id="onK-6l-2iV" customClass="DownloadTableCellView">
<rect key="frame" x="1" y="20" width="397" height="49"/>
<tableCellView focusRingType="none" id="onK-6l-2iV">
<rect key="frame" x="1" y="1" width="451" height="49"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="A44-us-TEl">
<rect key="frame" x="25" y="28" width="371" height="17"/>
<rect key="frame" x="41" y="28" width="409" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="NSU-6I-nsG">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="onK-6l-2iV" name="value" keyPath="objectValue.name" id="t1L-kM-AW6">
<dictionary key="options">
<string key="NSMultipleValuesPlaceholder">multiple</string>
<string key="NSNoSelectionPlaceholder">no selection</string>
<string key="NSNotApplicablePlaceholder">n/a</string>
<string key="NSNullPlaceholder">null</string>
</dictionary>
</binding>
<binding destination="onK-6l-2iV" name="textColor" keyPath="objectValue.titleColor" id="0Qx-rz-DEZ"/>
<binding destination="onK-6l-2iV" name="toolTip" keyPath="objectValue.value" id="rUb-Jb-KbT"/>
</connections>
</textField>
<progressIndicator wantsLayer="YES" fixedFrame="YES" maxValue="100" displayedWhenStopped="NO" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="jBN-UJ-tWi">
<rect key="frame" x="3" y="29" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</progressIndicator>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hfu-hP-QAH">
<rect key="frame" x="25" y="3" width="371" height="17"/>
<rect key="frame" x="41" y="3" width="409" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="1cQ-Zh-q0o">
<font key="font" metaFont="system"/>
<font key="font" metaFont="system" size="10"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="onK-6l-2iV" name="textColor" keyPath="objectValue.descriptionColor" id="KVi-3N-Swm"/>
<binding destination="onK-6l-2iV" name="value" keyPath="objectValue.statusDescription" id="yV1-5r-YDh"/>
</connections>
</textField>
<progressIndicator wantsLayer="YES" fixedFrame="YES" maxValue="100" displayedWhenStopped="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="jBN-UJ-tWi">
<rect key="frame" x="3" y="9" width="32" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<connections>
<binding destination="onK-6l-2iV" name="animate" keyPath="objectValue.task" id="d22-JL-3Z7">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
</connections>
</progressIndicator>
</subviews>
<connections>
<outlet property="activity" destination="jBN-UJ-tWi" id="ZwD-yU-Vne"/>
<outlet property="statusTextField" destination="hfu-hP-QAH" id="8Hv-BB-kYA"/>
<outlet property="textField" destination="A44-us-TEl" id="Ta5-nd-ed1"/>
<outlet property="textField" destination="A44-us-TEl" id="ude-er-Gm4"/>
</connections>
</tableCellView>
</prototypeCellViews>
<connections>
<binding destination="jhO-4z-Qwt" name="value" keyPath="arrangedObjects.selection" id="KQP-Xo-Fbf"/>
</connections>
</tableColumn>
</tableColumns>
<connections>
<outlet property="dataSource" destination="-2" id="Ghf-k9-bRK"/>
<outlet property="delegate" destination="-2" id="rpR-0W-4Nu"/>
<action trigger="doubleAction" selector="doubleClick:" target="-2" id="y2y-h7-cfD"/>
<binding destination="jhO-4z-Qwt" name="content" keyPath="arrangedObjects" id="2av-gV-V4K"/>
<outlet property="menu" destination="RJM-21-hjO" id="xpL-0n-1jm"/>
</connections>
</tableView>
@ -139,10 +134,22 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<textField verticalHuggingPriority="750" fixedFrame="YES" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sJz-So-jbA">
<rect key="frame" x="51" y="101" width="383" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="HKe-di-YSs">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="downloadURLChanged:" target="-2" id="ah1-QS-G27"/>
</connections>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Fhd-vr-Q2G">
<rect key="frame" x="20" y="19" width="124" height="23"/>
<rect key="frame" x="208" y="13" width="150" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="roundTextured" title="Download Missing" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="AKx-eg-iLS">
<buttonCell key="cell" type="push" title="Download Missing" bezelStyle="rounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="AKx-eg-iLS">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
@ -155,12 +162,134 @@
</binding>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d2z-4T-Wh1">
<rect key="frame" x="10" y="104" width="30" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="URL" id="lcZ-R4-WsS">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZXO-bJ-btp">
<rect key="frame" x="10" y="66" width="34" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Type" id="KGI-t9-OMF">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="AuM-pD-Gul">
<rect key="frame" x="12" y="52" width="422" height="5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<button verticalHuggingPriority="750" fixedFrame="YES" imageHugsTitle="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dpY-qZ-2Nk">
<rect key="frame" x="93" y="13" width="115" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="push" title="ROMs" bezelStyle="rounded" image="NSFolder" imagePosition="left" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="E0t-sX-rgE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="showRomFolder:" target="-2" id="bys-Vs-b4m"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Lnv-mh-zAr">
<rect key="frame" x="6" y="13" width="87" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="push" title="Refresh" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="mYS-h7-GUa">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent">r</string>
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</buttonCell>
<connections>
<action selector="refreshROMs:" target="-2" id="E7j-Fa-IN1"/>
</connections>
</button>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2Rg-eX-DUq">
<rect key="frame" x="49" y="60" width="98" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<popUpButtonCell key="cell" type="push" title="zip" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" selectedItem="7Cq-Lh-dgg" id="uum-dC-XD0">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" autoenablesItems="NO" id="kcg-aZ-mD9">
<items>
<menuItem title="zip" state="on" tag="1" id="7Cq-Lh-dgg"/>
<menuItem title="7z" tag="2" id="s5r-gg-Ma9"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="downloadExtensionChanged:" target="-2" id="tp2-tg-bms"/>
<binding destination="-2" name="selectedTag" keyPath="self.downloadExtension" id="uck-nA-UPg">
<dictionary key="options">
<string key="NSValueTransformerName">DownloadExtensionTransformer</string>
</dictionary>
</binding>
</connections>
</popUpButton>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rg5-Qf-4Mw">
<rect key="frame" x="358" y="13" width="82" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="i6Z-OM-lqE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent">.</string>
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
<connections>
<binding destination="-2" name="enabled" keyPath="self.active" id="mBP-8S-yGB"/>
</connections>
</buttonCell>
<connections>
<action selector="cancelAll:" target="-2" id="ycl-eJ-ByB"/>
</connections>
</button>
</subviews>
</view>
<toolbar key="toolbar" implicitIdentifier="B60021E6-BFBC-44E6-97DC-120AA9FD3269" autosavesConfiguration="NO" allowsUserCustomization="NO" displayMode="iconOnly" sizeMode="regular" id="kpz-W4-xgh">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="tbY-ts-Irb"/>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="3Kc-zG-IdN"/>
<toolbarItem implicitItemIdentifier="BD743A15-0B61-48FF-9EED-FD8D57EF8459" label="All" paletteLabel="All" tag="1" sizingBehavior="auto" id="Jj0-n8-I5a">
<nil key="toolTip"/>
<button key="view" verticalHuggingPriority="750" tag="1" id="Kgj-LP-FsF">
<rect key="frame" x="0.0" y="14" width="74" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="recessed" title="All" bezelStyle="recessed" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="9s7-S1-hW1">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<connections>
<action selector="filterButton:" target="-2" id="gTc-Ul-FYR"/>
</connections>
</button>
</toolbarItem>
<toolbarItem implicitItemIdentifier="5B013840-E582-4568-8448-DDD7EE1E5AE2" label="Missing" paletteLabel="Missing" tag="2" sizingBehavior="auto" id="GV4-aX-5Ox">
<nil key="toolTip"/>
<button key="view" verticalHuggingPriority="750" tag="2" id="6c7-tU-3F3">
<rect key="frame" x="0.0" y="14" width="74" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="recessed" title="Missing" bezelStyle="recessed" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ui2-dz-IZj">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<connections>
<action selector="filterButton:" target="-2" id="R6W-hU-oqL"/>
</connections>
</button>
</toolbarItem>
</allowedToolbarItems>
<defaultToolbarItems>
<toolbarItem reference="Jj0-n8-I5a"/>
<toolbarItem reference="GV4-aX-5Ox"/>
</defaultToolbarItems>
</toolbar>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="142" y="179"/>
<point key="canvasLocation" x="59" y="119.5"/>
</window>
<menu id="RJM-21-hjO">
<items>
@ -170,6 +299,12 @@
<action selector="showInFinder:" target="-2" id="ltL-yL-7EP"/>
</connections>
</menuItem>
<menuItem title="Move to Trash" id="x1Q-OF-5hM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="moveToTrash:" target="-2" id="swr-yf-hA2"/>
</connections>
</menuItem>
<menuItem title="Download" tag="2" id="ree-Zg-jYB">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
@ -188,5 +323,10 @@
</connections>
<point key="canvasLocation" x="-348" y="164"/>
</menu>
<arrayController objectClassName="DownloadItem" editable="NO" preservesSelection="NO" selectsInsertedObjects="NO" avoidsEmptySelection="NO" clearsFilterPredicateOnInsertion="NO" automaticallyRearrangesObjects="YES" id="jhO-4z-Qwt" customClass="DownloadItemArrayController"/>
<userDefaultsController representsSharedInstance="YES" id="721-9N-Bma"/>
</objects>
<resources>
<image name="NSFolder" width="32" height="32"/>
</resources>
</document>

View File

@ -8,66 +8,474 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="LaunchWindowController">
<connections>
<outlet property="addBookmarkWindow" destination="yIt-hP-HBq" id="Qhx-WV-cg4"/>
<outlet property="bookmarkErrorField" destination="RiJ-Xw-sgW" id="6y5-Fo-AnM"/>
<outlet property="bookmarkTextField" destination="fAl-Vn-x1w" id="GNr-j6-BiQ"/>
<outlet property="machineView" destination="oVt-eD-aaj" id="Q9V-Kr-6GN"/>
<outlet property="machineViewController" destination="RgH-d9-xl8" id="DIa-h0-6y2"/>
<outlet property="machineViewController" destination="FSD-3v-Wni" id="tXv-zJ-QO3"/>
<outlet property="mediaController" destination="t7c-zy-czN" id="a7d-HC-TWx"/>
<outlet property="mediaView" destination="J9O-xI-P5J" id="PmZ-VC-4SN"/>
<outlet property="slotController" destination="lyS-mc-3Tf" id="LXo-Ii-fDX"/>
<outlet property="slotView" destination="P9d-sS-qEb" id="qlH-u0-hzq"/>
<outlet property="softwareListControl" destination="pNl-g4-ZLh" id="U0i-R9-GLE"/>
<outlet property="window" destination="Vze-YF-m6e" id="JUs-Eb-MW8"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Ample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="Vze-YF-m6e">
<window title="Ample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="LaunchWindow" animationBehavior="default" id="Vze-YF-m6e">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="335" y="390" width="718" height="763"/>
<rect key="contentRect" x="335" y="390" width="1000" height="640"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="Ssv-Jw-EE0">
<rect key="frame" x="0.0" y="0.0" width="718" height="763"/>
<rect key="frame" x="0.0" y="0.0" width="1000" height="640"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oVt-eD-aaj">
<rect key="frame" x="0.0" y="563" width="718" height="200"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<customView id="P9d-sS-qEb" customClass="FlippedView">
<rect key="frame" x="302" y="105" width="326" height="363"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
</customView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zVI-uU-muo">
<rect key="frame" x="18" y="102" width="71" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="check" title="Window" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="vx1-I7-8kN">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<tabView initialItem="zUN-Qs-haG" id="l8R-bg-6Zm">
<rect key="frame" x="295" y="466" width="692" height="160"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<font key="font" metaFont="system"/>
<tabViewItems>
<tabViewItem label="Video" identifier="" id="zUN-Qs-haG">
<view key="view" id="QQT-HS-xjI">
<rect key="frame" x="10" y="33" width="672" height="114"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pD8-dV-ijg">
<rect key="frame" x="143" y="87" width="172" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Default" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="g0W-Ka-7bb" id="ceP-aK-me8">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="ajo-1k-sbD">
<items>
<menuItem title="Default" state="on" id="g0W-Ka-7bb"/>
<menuItem title="Metal" tag="1" id="93g-cb-opl"/>
<menuItem title="OpenGL" tag="2" id="B1R-9E-dMw"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<binding destination="-2" name="enabled" keyPath="self.mameBGFX" id="ZuQ-OY-TrP"/>
<binding destination="-2" name="selectedIndex" keyPath="self.mameBackend" id="oE1-Ho-H22"/>
</connections>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qGO-Pm-SD1">
<rect key="frame" x="79" y="92" width="60" height="16"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Backend:" id="WDr-Pl-lV1">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ctE-fX-twN">
<rect key="frame" x="318" y="92" width="51" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Effects:" id="Sqk-7k-PxQ">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="826-p8-in8">
<rect key="frame" x="15" y="91" width="57" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="BGFX" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Ubs-KZ-mpu">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameBGFX" id="9Ua-MZ-qbe"/>
</connections>
</button>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hM8-FM-Agh">
<rect key="frame" x="382" y="87" width="174" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Default" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Dsm-bi-Txy" id="mBS-h4-BWC">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="WdF-Hw-YI9">
<items>
<menuItem title="Default" state="on" id="Dsm-bi-Txy">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Unfiltered" tag="1" id="xgz-We-TFg">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="HLSL" tag="2" id="1UE-ea-V9a">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="CRT Geometry" tag="3" id="Dsx-wI-m3r">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="CRT Geometry Deluxe" tag="4" id="Ylw-Of-TM5">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="LCD Grid" tag="5" id="A6k-ku-z2M">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Fighters" id="1aA-ge-f8R">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</popUpButtonCell>
<connections>
<binding destination="-2" name="enabled" keyPath="self.mameBGFX" id="DVB-Ex-VYF"/>
<binding destination="-2" name="selectedIndex" keyPath="self.mameEffects" id="rCg-d6-OR6"/>
</connections>
</popUpButton>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="D5h-dm-fuZ">
<rect key="frame" x="318" y="60" width="104" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Square Pixels" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="yWK-BP-7Z9">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameSquarePixels" id="BiP-wC-Hpn"/>
<binding destination="-2" name="enabled" keyPath="self.mameWindowMode" id="X80-2K-kTO"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6gd-45-eLr">
<rect key="frame" x="15" y="60" width="94" height="16"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Window Mode:" id="l8n-CI-o4t">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sei-LG-VM6">
<rect key="frame" x="143" y="55" width="172" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Full Screen" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="0zZ-Ib-Fne" id="lsw-Vk-WcZ">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="m4N-Qw-mem">
<items>
<menuItem title="Full Screen" state="on" id="0zZ-Ib-Fne">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Window 1x" id="3bZ-rq-fCt">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Window 2x" id="KA4-Rs-yyK">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Window 3x" id="Dbh-Js-pMx" userLabel="Window 3x">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Window 4x" id="GCs-En-3Jv">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</popUpButtonCell>
<connections>
<binding destination="-2" name="selectedIndex" keyPath="self.mameWindowMode" id="B9e-SK-3RY"/>
</connections>
</popUpButton>
<button verticalHuggingPriority="750" id="9Db-wA-FP9">
<rect key="frame" x="15" y="29" width="115" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Capture Mouse" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="3xh-Q7-WFl">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameMouse" id="vWu-od-2d6"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XNa-8k-X89">
<rect key="frame" x="143" y="29" width="137" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Disk Sound Effects" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="MBT-Uv-Lev">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameSamples" id="77G-8C-HgT"/>
</connections>
</button>
</subviews>
</view>
</tabViewItem>
<tabViewItem label="CPU" identifier="" id="nr5-4o-DyG">
<view key="view" id="ElY-YI-LLI">
<rect key="frame" x="10" y="33" width="672" height="114"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZUp-ni-Rr6">
<rect key="frame" x="15" y="60" width="62" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Debug" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="6is-QN-JEc">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameDebug" id="vkc-sR-KnB"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PGK-yK-2ZK">
<rect key="frame" x="15" y="91" width="43" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Speed" id="D9w-Mz-PXs">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FE4-gG-fPb">
<rect key="frame" x="62" y="86" width="109" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="100%" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="proportionallyDown" inset="2" selectedItem="yoI-Ra-evu" id="M40-f0-awc">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="8Tv-0j-JhQ">
<items>
<menuItem title="100%" state="on" tag="1" id="yoI-Ra-evu"/>
<menuItem title="200%" tag="2" id="UqT-yd-8o3"/>
<menuItem title="300%" tag="3" id="awG-S1-uM4"/>
<menuItem title="400%" tag="4" id="qJ5-Ed-W5U"/>
<menuItem title="500%" tag="5" id="Phc-uW-Qog"/>
<menuItem title="No Throttle" tag="-1" id="gAc-ME-eim"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<binding destination="-2" name="selectedTag" keyPath="self.mameSpeed" id="nFG-yA-KC1"/>
</connections>
</popUpButton>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="knB-Rn-1Cm">
<rect key="frame" x="15" y="40" width="67" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Rewind" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Y7b-jN-HCc">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameRewind" id="Hw5-n7-O27"/>
</connections>
</button>
</subviews>
</view>
</tabViewItem>
<tabViewItem label="A/V" identifier="" id="0T5-BN-lxE">
<view key="view" id="knw-WE-UU3">
<rect key="frame" x="10" y="33" width="672" height="114"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vWt-Dx-OGG">
<rect key="frame" x="15" y="91" width="102" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Generate AVI" bezelStyle="regularSquare" imagePosition="left" inset="2" id="hRp-Lh-Ebr">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
<connections>
<binding destination="-2" name="value" keyPath="self.mameAVI" id="G1O-YP-DXa"/>
</connections>
</buttonCell>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ejn-wC-UXH">
<rect key="frame" x="15" y="60" width="110" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Generate WAV" bezelStyle="regularSquare" imagePosition="left" inset="2" id="7Aa-N2-MHn">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameWAV" id="4r0-ZQ-nNC"/>
</connections>
</button>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5Yf-ZJ-8kx">
<rect key="frame" x="132" y="59" width="523" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="/path/to/file.wav" drawsBackground="YES" usesSingleLineMode="YES" id="Xqc-zw-28b">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="enabled" keyPath="self.mameWAV" id="lZM-6n-jAS"/>
<binding destination="-2" name="value" keyPath="self.mameWAVPath" id="475-s3-0e4">
<dictionary key="options">
<string key="NSNullPlaceholder">/path/to/file.wav</string>
</dictionary>
</binding>
</connections>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ne8-5I-D1H">
<rect key="frame" x="132" y="28" width="523" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="/path/to/file.vgm" drawsBackground="YES" usesSingleLineMode="YES" id="xGs-Mi-wzj">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<connections>
<binding destination="-2" name="enabled" keyPath="self.mameVGM" id="TJV-4j-uVi"/>
<binding destination="-2" name="value" keyPath="self.mameVGMPath" id="aK1-2A-QWB">
<dictionary key="options">
<string key="NSNoSelectionPlaceholder">/path/to/file.vgm</string>
</dictionary>
</binding>
</connections>
</textFieldCell>
<connections>
<binding destination="-2" name="enabled" keyPath="self.mameVGM" id="JZX-dA-3Bn"/>
<binding destination="-2" name="value" keyPath="self.mameVGMPath" id="m7G-a0-QDZ">
<dictionary key="options">
<string key="NSNullPlaceholder">/path/to/file.vgm</string>
</dictionary>
</binding>
</connections>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Xht-PS-Hw8">
<rect key="frame" x="132" y="90" width="523" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="/path/to/file.avi" drawsBackground="YES" usesSingleLineMode="YES" id="iY4-FF-x2e">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="enabled" keyPath="self.mameAVI" id="o4R-KR-zVV"/>
<binding destination="-2" name="value" keyPath="self.mameAVIPath" id="dSK-1u-lh6">
<dictionary key="options">
<string key="NSNullPlaceholder">/path/to/file.avi</string>
</dictionary>
</binding>
</connections>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YVz-a3-9Pj">
<rect key="frame" x="15" y="29" width="111" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Generate VGM" bezelStyle="regularSquare" imagePosition="left" inset="2" id="F9b-kg-ZMV">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameVGM" id="Oyp-Pc-Uad"/>
</connections>
</button>
</subviews>
</view>
</tabViewItem>
<tabViewItem label="Paths" identifier="" id="PVN-Iw-nYG">
<view key="view" id="5qP-bQ-Id6">
<rect key="frame" x="10" y="33" width="672" height="114"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VDW-FX-9az">
<rect key="frame" x="132" y="90" width="523" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="/path/to/directory/" drawsBackground="YES" usesSingleLineMode="YES" id="ykl-aj-n1L">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="enabled" keyPath="self.mameShareDirectory" id="bPv-hU-XgK"/>
<binding destination="-2" name="value" keyPath="self.mameShareDirectoryPath" id="ddj-BN-tsY">
<dictionary key="options">
<string key="NSNullPlaceholder">/path/to/directory/</string>
</dictionary>
</binding>
</connections>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1fA-nr-wns">
<rect key="frame" x="15" y="91" width="117" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Share Directory" bezelStyle="regularSquare" imagePosition="left" inset="2" id="xmA-1v-wU7">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameShareDirectory" id="x3D-ho-u4v"/>
</connections>
</button>
</subviews>
</view>
</tabViewItem>
</tabViewItems>
<connections>
<binding destination="-2" name="value" keyPath="self.mameWindow" id="uS7-cg-wqb"/>
<binding destination="-2" name="hidden" keyPath="machine" id="odt-eJ-VrX">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZUp-ni-Rr6">
<rect key="frame" x="18" y="82" width="62" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="check" title="Debug" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="6is-QN-JEc">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameDebug" id="vkc-sR-KnB"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pKK-yY-vnY">
<rect key="frame" x="0.0" y="0.0" width="718" height="52"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="bk2-0p-jUj">
</tabView>
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="J9O-xI-P5J" customClass="FlippedView">
<rect key="frame" x="654" y="107" width="326" height="331"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
</customView>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" id="2ue-XT-byh">
<rect key="frame" x="0.0" y="0.0" width="1001" height="69"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="eSY-AU-tvi">
<rect key="frame" x="0.0" y="0.0" width="1001" height="69"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView focusRingType="none" editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" allowsCharacterPickerTouchBarItem="NO" textCompletion="NO" id="c0R-8x-RL2">
<rect key="frame" x="0.0" y="0.0" width="1001" height="69"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="1001" height="69"/>
<size key="maxSize" width="1001" height="10000000"/>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
<connections>
<binding destination="-2" name="value" keyPath="self.commandLine" id="deQ-gK-fgu">
<dictionary key="options">
<bool key="NSConditionallySetsEditable" value="NO"/>
</dictionary>
</binding>
</connections>
</textView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="qto-12-JOq">
<rect key="frame" x="-100" y="-100" width="225" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="FPs-uz-0v2">
<rect key="frame" x="703" y="0.0" width="15" height="51"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<searchField wantsLayer="YES" verticalHuggingPriority="750" textCompletion="NO" id="pNl-g4-ZLh" customClass="AutocompleteControl">
<rect key="frame" x="654" y="446" width="326" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="Software List" usesSingleLineMode="YES" bezelStyle="round" id="sMi-a3-XEn">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<color key="backgroundColor" name="systemRedColor" catalog="System" colorSpace="catalog"/>
</searchFieldCell>
<connections>
<binding destination="-2" name="value" keyPath="self.commandLine" id="9gW-Y2-kvp"/>
<action selector="softwareChanged:" target="-2" id="879-da-UEc"/>
</connections>
</textField>
</searchField>
<customView id="oVt-eD-aaj" customClass="FlippedView">
<rect key="frame" x="0.0" y="69" width="294" height="571"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</customView>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="UwI-q9-hEm">
<rect key="frame" x="0.0" y="67" width="1000" height="5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<box horizontalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="xjH-Gv-MHt">
<rect key="frame" x="291" y="69" width="5" height="571"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" heightSizable="YES"/>
</box>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nKp-px-nHg">
<rect key="frame" x="587" y="58" width="111" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<rect key="frame" x="869.5" y="76" width="111" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="roundTextured" title="Launch" bezelStyle="texturedRounded" image="NSAppleMenuImage" imagePosition="left" alignment="center" borderStyle="border" inset="2" id="Ct1-Rb-7uI">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -78,69 +486,187 @@ DQ
</buttonCell>
<connections>
<action selector="launchAction:" target="-2" id="a4d-zv-1CU"/>
<binding destination="-2" name="hidden" keyPath="machine" id="8Ks-FY-Tmk">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rLP-n2-0eY">
<rect key="frame" x="18" y="62" width="91" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="check" title="No Throttle" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="NyE-jT-WqC">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameNoThrottle" id="tUN-EX-7PF"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="D5h-dm-fuZ">
<rect key="frame" x="131" y="102" width="104" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="check" title="Square Pixels" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="yWK-BP-7Z9">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameSquarePixels" id="BiP-wC-Hpn"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zoQ-mU-ARl">
<rect key="frame" x="261" y="102" width="67" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="check" title="No Blur" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="r3s-5h-Xv5">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="self.mameNoBlur" id="Pvn-zw-OsQ"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nNO-3T-OAy">
<rect key="frame" x="470" y="58" width="109" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="roundTextured" title="Reset Slots" bezelStyle="texturedRounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Uii-5h-2R2">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent">r</string>
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</buttonCell>
<connections>
<action selector="resetSlots:" target="lyS-mc-3Tf" id="1qi-N0-Q8B"/>
</connections>
</button>
<customView id="P9d-sS-qEb" customClass="FlippedView">
<rect key="frame" x="20" y="155" width="306" height="400"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</customView>
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="J9O-xI-P5J" customClass="FlippedView">
<rect key="frame" x="392" y="155" width="306" height="400"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
</customView>
</subviews>
</view>
<point key="canvasLocation" x="769" y="104.5"/>
<toolbar key="toolbar" implicitIdentifier="ACA8EE70-5505-4CFD-9F78-7A480D93260B" autosavesConfiguration="NO" allowsUserCustomization="NO" prefersToBeShown="NO" displayMode="iconAndLabel" sizeMode="regular" id="b3J-Bx-3nk">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarShowColorsItem" id="uHd-dY-alN"/>
<toolbarItem implicitItemIdentifier="NSToolbarShowFontsItem" id="WEM-Gw-Utx"/>
<toolbarItem implicitItemIdentifier="NSToolbarPrintItem" id="RCG-fn-6Ue"/>
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="BRc-Qf-FCk"/>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="Dtt-KT-5NO"/>
</allowedToolbarItems>
<defaultToolbarItems/>
</toolbar>
<connections>
<outlet property="menu" destination="Aa5-Sk-gZX" id="Sj0-0o-oZb"/>
</connections>
<point key="canvasLocation" x="590" y="40"/>
</window>
<viewController title="Media View" nibName="MediaView" id="t7c-zy-czN" customClass="MediaViewController"/>
<viewController title="Slot View" nibName="SlotView" id="lyS-mc-3Tf" customClass="SlotViewController"/>
<customObject id="RgH-d9-xl8" customClass="MachineViewController"/>
<window title="Add Bookmark" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="yIt-hP-HBq">
<windowStyleMask key="styleMask" titled="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="462" height="116"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" wantsLayer="YES" id="WVd-g4-Tbl">
<rect key="frame" x="0.0" y="0.0" width="462" height="116"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Gho-Xy-rn4">
<rect key="frame" x="358" y="13" width="90" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Add" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Vxo-rD-aMe">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
</buttonCell>
<connections>
<action selector="bookmarkSave:" target="-2" id="wLF-LE-5RO"/>
<binding destination="-2" name="enabled" keyPath="bookmarkName" id="U5R-gU-1bE">
<dictionary key="options">
<string key="NSValueTransformerName">StringNotEmptyTransformer</string>
</dictionary>
</binding>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3sv-Kd-Ep5">
<rect key="frame" x="268" y="13" width="90" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="jaa-RY-PAg">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell>
<connections>
<action selector="bookmarkCancel:" target="-2" id="uWM-vs-hz7"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1fO-x7-Gft">
<rect key="frame" x="18" y="80" width="103" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Add Bookmark…" id="AZS-JR-SNt">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fAl-Vn-x1w">
<rect key="frame" x="20" y="49" width="422" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="bookmark name" drawsBackground="YES" id="Enq-2z-cle">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="value" keyPath="bookmarkName" id="84v-el-4Uk">
<dictionary key="options">
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
<string key="NSNullPlaceholder">bookmark name</string>
</dictionary>
</binding>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RiJ-Xw-sgW">
<rect key="frame" x="20" y="20" width="248" height="16"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="Ehz-4Z-Tjq">
<font key="font" metaFont="system"/>
<color key="textColor" name="systemRedColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EFq-dZ-y90">
<rect key="frame" x="378" y="79" width="66" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Default" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="cOs-WH-9Dr">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="bookmarkDefault" id="Oiv-hR-5fn"/>
</connections>
</button>
</subviews>
</view>
<point key="canvasLocation" x="-62" y="95"/>
</window>
<viewController nibName="MachineView" id="FSD-3v-Wni" customClass="NewMachineViewController"/>
<menu id="Aa5-Sk-gZX">
<items>
<menuItem title="Launch" image="NSAppleMenuImage" id="OSH-7C-D6z">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="launchAction:" target="-2" id="ZY2-He-VyK"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="Iti-F9-p35"/>
<menuItem title="List Media…" id="M5h-4W-0nV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="listMedia:" target="-2" id="IO7-MG-zud"/>
<binding destination="-2" name="hidden" keyPath="optionKey" id="LhL-2l-iss">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</menuItem>
<menuItem title="List Slots…" id="cNj-Sb-KkE">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="listSlots:" target="-2" id="3nb-mV-eUK"/>
<binding destination="-2" name="hidden" keyPath="optionKey" id="dwp-Kn-LfC">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="yZx-W2-lZg"/>
<menuItem title="Reset All" id="PQ0-yO-SKz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="resetAll:" target="-2" id="hF5-fl-bMr"/>
</connections>
</menuItem>
<menuItem title="Reset Machine" id="1by-3B-LSd">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="resetMachine:" target="-2" id="7au-OM-Q88"/>
</connections>
</menuItem>
<menuItem title="Reset Slots" id="ccx-xm-qeo">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="resetSlots:" target="lyS-mc-3Tf" id="39K-rS-u9D"/>
</connections>
</menuItem>
<menuItem title="Reset Media" id="Opr-7k-fO1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="resetMedia:" target="-2" id="n5j-1R-NJl"/>
</connections>
</menuItem>
</items>
<connections>
<outlet property="delegate" destination="-2" id="wqC-IG-63F"/>
</connections>
<point key="canvasLocation" x="-121" y="-2"/>
</menu>
</objects>
<resources>
<image name="NSAppleMenuImage" width="11" height="14"/>

View File

@ -21,7 +21,7 @@
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="800" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Hj3-ou-djb">
<rect key="frame" x="0.0" y="0.0" width="800" height="270"/>
@ -52,10 +52,31 @@
</scrollView>
</subviews>
</view>
<toolbar key="toolbar" implicitIdentifier="54C242E0-0A7F-491A-9B83-7279A9663A36" autosavesConfiguration="NO" allowsUserCustomization="NO" displayMode="iconOnly" sizeMode="small" id="Cik-bA-ZYu">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarShowColorsItem" id="zxC-EA-a7F"/>
<toolbarItem implicitItemIdentifier="NSToolbarShowFontsItem" id="xZv-cQ-rPS"/>
<toolbarItem implicitItemIdentifier="NSToolbarPrintItem" id="2BZ-oP-sMg"/>
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="j5G-hW-61a"/>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="a72-iv-2QT"/>
<toolbarItem implicitItemIdentifier="21A9965C-D1B3-4E82-A344-1688A467E870" label="Clear Log" paletteLabel="Clear Log" tag="-1" image="NSTrashEmpty" id="pn5-MM-9p1">
<connections>
<action selector="clearLog:" target="-2" id="VU3-mv-6WR"/>
</connections>
</toolbarItem>
</allowedToolbarItems>
<defaultToolbarItems>
<toolbarItem reference="a72-iv-2QT"/>
<toolbarItem reference="pn5-MM-9p1"/>
</defaultToolbarItems>
</toolbar>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="-285" y="-234"/>
</window>
</objects>
<resources>
<image name="NSTrashEmpty" width="32" height="32"/>
</resources>
</document>

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NewMachineViewController">
<connections>
<outlet property="outlineView" destination="9V6-He-b8A" id="XeC-DJ-oXY"/>
<outlet property="view" destination="t3T-qF-D0e" id="Svb-w7-hs9"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" id="t3T-qF-D0e">
<rect key="frame" x="0.0" y="0.0" width="274" height="543"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" drawsBackground="NO" id="DyG-qq-uBF">
<rect key="frame" x="0.0" y="0.0" width="274" height="543"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" autosaveName="machine-view" rowHeight="24" rowSizeStyle="automatic" viewBased="YES" indentationPerLevel="16" autosaveExpandedItems="YES" outlineTableColumn="e67-js-boV" id="9V6-He-b8A">
<rect key="frame" x="0.0" y="0.0" width="274" height="543"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" white="1" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="271" minWidth="16" maxWidth="1000" id="e67-js-boV">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="jZU-xV-PI4">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="HeaderCell" id="2iF-4F-HfC">
<rect key="frame" x="1" y="1" width="271" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9tU-X8-FZn">
<rect key="frame" x="0.0" y="0.0" width="271" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="HEADER CELL" id="EUi-TS-vlq">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="2iF-4F-HfC" name="value" keyPath="objectValue.description" id="He3-9c-g9A"/>
</connections>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="9tU-X8-FZn" id="p2B-eV-6bS"/>
</connections>
</tableCellView>
<tableCellView identifier="DataCell" id="7b4-T1-d29">
<rect key="frame" x="1" y="20" width="271" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FkS-zP-pRB">
<rect key="frame" x="0.0" y="0.0" width="271" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="g6t-E7-0lM">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="7b4-T1-d29" name="value" keyPath="objectValue.description" id="kp8-ww-1aE"/>
</connections>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="FkS-zP-pRB" id="JkE-pr-7px"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<action selector="clickAction:" target="-2" id="O3p-cV-gwk"/>
<outlet property="dataSource" destination="-2" id="nW2-qs-3w6"/>
<outlet property="delegate" destination="-2" id="4Wc-Pe-v81"/>
</connections>
</outlineView>
</subviews>
<nil key="backgroundColor"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="kig-a5-Ay0">
<rect key="frame" x="-100" y="-100" width="238" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="lLp-pv-Fbj" customClass="TransparentScroller">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<point key="canvasLocation" x="-91" y="132"/>
</scrollView>
</objects>
</document>

View File

@ -13,12 +13,19 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customObject id="rSq-qV-SGy" customClass="BookmarkManager">
<connections>
<outlet property="menu" destination="ha0-nx-PIl" id="Ozd-ID-egK"/>
<outlet property="updateMenuItem" destination="30b-vT-HIa" id="AgZ-LE-no6"/>
</connections>
</customObject>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate">
<connections>
<outlet property="installWindow" destination="jWX-pY-Zpb" id="xAj-Vj-Vxn"/>
</connections>
</customObject>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="3aq-Tx-mno" customClass="SUUpdater"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Ample" id="1Xt-HY-uBw">
@ -31,13 +38,16 @@
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem title="Manage ROMs…" id="St3-qR-2Y8">
<menuItem title="Check for Updates…" id="CPy-r4-rzr">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="downloadROMS:" target="Voe-Tx-rLC" id="jFm-nv-kRC"/>
<action selector="checkForUpdates:" target="3aq-Tx-mno" id="qJG-Nv-0Lu"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Reinstall MAME components" hidden="YES" id="c3P-WT-eUP">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW">
<connections>
<action selector="displayPreferences:" target="Voe-Tx-rLC" id="Hsm-pX-sUc"/>
@ -123,6 +133,12 @@
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
<menuItem title="Export Shell Script…" id="LmB-h2-UBZ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="exportShellScript:" target="-1" id="9eU-do-ffz"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
@ -357,268 +373,6 @@
</items>
</menu>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
<items>
<menuItem title="Font" id="Gi5-1S-RQB">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
<connections>
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
<connections>
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
<menuItem title="Kern" id="jBQ-r6-VK2">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
<items>
<menuItem title="Use Default" id="GUa-eO-cwY">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
</connections>
</menuItem>
<menuItem title="Use None" id="cDB-IK-hbR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="46P-cB-AYj">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="ogc-rX-tC1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="o6e-r0-MWq">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
<items>
<menuItem title="Use Default" id="agt-UL-0e3">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
</connections>
</menuItem>
<menuItem title="Use None" id="J7y-lM-qPV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
</connections>
</menuItem>
<menuItem title="Use All" id="xQD-1f-W4t">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="OaQ-X3-Vso">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
<items>
<menuItem title="Use Default" id="3Om-Ey-2VK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="Rqc-34-cIF">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="I0S-gh-46l">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
</connections>
</menuItem>
<menuItem title="Raise" id="2h7-ER-AoG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
</connections>
</menuItem>
<menuItem title="Lower" id="1tx-W0-xDw">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
<connections>
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="Fal-I4-PZk">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="d9c-me-L2H">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
<connections>
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
<connections>
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
</connections>
</menuItem>
<menuItem title="Justify" id="J5U-5w-g23">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
<connections>
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
<menuItem title="Writing Direction" id="H1b-Si-o9J">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
<items>
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="YGs-j5-SAR">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
</connections>
</menuItem>
<menuItem id="Lbh-J2-qVU">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
</connections>
</menuItem>
<menuItem id="jFq-tB-4Kx">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="Nop-cj-93Q">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
</connections>
</menuItem>
<menuItem id="BgM-ve-c93">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
</connections>
</menuItem>
<menuItem id="RB4-Sm-HuC">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
<menuItem title="Show Ruler" id="vLm-3I-IUL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
@ -651,6 +405,45 @@
</items>
</menu>
</menuItem>
<menuItem title="Bookmarks" id="vHO-2e-qJc">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Bookmarks" id="ha0-nx-PIl">
<items>
<menuItem title="Manage Bookmarks…" keyEquivalent="b" id="isI-q6-b1V">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="manageBookmarks:" target="-1" id="vOm-90-AoO"/>
</connections>
</menuItem>
<menuItem title="Add Bookmark…" keyEquivalent="d" id="1JF-xV-zmG">
<connections>
<action selector="addBookmark:" target="-1" id="cqp-ko-BfQ"/>
</connections>
</menuItem>
<menuItem title="Update Bookmark" keyEquivalent="D" id="30b-vT-HIa">
<connections>
<action selector="updateBookmark:" target="-1" id="Au0-Sp-cUD"/>
</connections>
</menuItem>
<menuItem title="Set Default" hidden="YES" id="vbR-vS-lqO">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="defaultSave:" target="-1" id="FP9-EX-OKP"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="gWR-Yl-mg6"/>
<menuItem title="Default" hidden="YES" id="mXC-Lp-gem">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="defaultLoad:" target="-1" id="ErS-k6-azP"/>
</connections>
</menuItem>
</items>
<connections>
<outlet property="delegate" destination="rSq-qV-SGy" id="Z7N-CG-hU1"/>
</connections>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
@ -666,6 +459,25 @@
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kE9-em-OHN"/>
<menuItem title="Ample Support Directory…" id="egj-hU-EtE">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="displaySupportDirectory:" target="Voe-Tx-rLC" id="XDA-Bv-9BJ"/>
</connections>
</menuItem>
<menuItem title="Manage ROMs…" id="St3-qR-2Y8">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="displayROMS:" target="Voe-Tx-rLC" id="jFm-nv-kRC"/>
</connections>
</menuItem>
<menuItem title="Recent Disk Images…" id="QY9-lF-kDy">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="displayRecentDiskImages:" target="Voe-Tx-rLC" id="9W1-nJ-8eJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
@ -685,6 +497,30 @@
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
</connections>
</menuItem>
<menuItem title="MAME Keyboard Cheat Sheet" id="vcW-Dz-2Nx">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="displayCheatSheet:" target="Voe-Tx-rLC" id="HvD-mQ-4pe"/>
</connections>
</menuItem>
<menuItem title="MAME Apple II Wiki" id="GLh-Cc-5uU">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="mameAppleWiki:" target="Voe-Tx-rLC" id="jRe-m6-mP0"/>
</connections>
</menuItem>
<menuItem title="MAME Mac 68K Wiki" id="hDL-K6-iVF">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="mameMac68kWiki:" target="Voe-Tx-rLC" id="ZzB-54-vXN"/>
</connections>
</menuItem>
<menuItem title="MAME Documentation" id="1IW-V0-UWA">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="mameDocumentation:" target="Voe-Tx-rLC" id="K8T-nZ-c5J"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
@ -711,5 +547,6 @@
</view>
<point key="canvasLocation" x="13" y="-182"/>
</window>
<userDefaultsController representsSharedInstance="YES" id="uGS-pc-Wsn"/>
</objects>
</document>

View File

@ -14,21 +14,20 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="20" horizontalPageScroll="10" verticalLineScroll="20" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="nVT-kT-bWl">
<rect key="frame" x="0.0" y="0.0" width="306" height="400"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="IBD-wb-pch">
<rect key="frame" x="0.0" y="0.0" width="306" height="400"/>
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="25" horizontalPageScroll="10" verticalLineScroll="25" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="nVT-kT-bWl">
<rect key="frame" x="0.0" y="0.0" width="316" height="331"/>
<clipView key="contentView" autoresizesSubviews="NO" focusRingType="none" ambiguous="YES" drawsBackground="NO" copiesOnScroll="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IBD-wb-pch">
<rect key="frame" x="0.0" y="0.0" width="316" height="331"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" selectionHighlightStyle="none" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" viewBased="YES" outlineTableColumn="pBj-py-R6a" id="sIz-DD-PZQ">
<rect key="frame" x="0.0" y="0.0" width="306" height="400"/>
<outlineView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" selectionHighlightStyle="none" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="22" rowSizeStyle="automatic" viewBased="YES" outlineTableColumn="pBj-py-R6a" id="sIz-DD-PZQ">
<rect key="frame" x="0.0" y="0.0" width="316" height="331"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="2" height="3"/>
<color key="backgroundColor" white="1" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn editable="NO" width="304" minWidth="40" maxWidth="1000" id="pBj-py-R6a">
<tableColumn editable="NO" width="296" minWidth="40" maxWidth="1000" id="pBj-py-R6a">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
@ -39,75 +38,210 @@
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews>
<tableCellView id="e4I-r0-vWM">
<rect key="frame" x="1" y="1" width="304" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Mig-Wj-m5e">
<rect key="frame" x="0.0" y="0.0" width="304" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="ZcN-bl-2D8">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="Mig-Wj-m5e" id="FYh-hX-PTU"/>
</connections>
</tableCellView>
<tableCellView identifier="CategoryView" focusRingType="none" id="33q-UT-ur5">
<rect key="frame" x="1" y="21" width="304" height="17"/>
<rect key="frame" x="1" y="1" width="296" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Pep-mX-LHY">
<rect key="frame" x="0.0" y="0.0" width="304" height="17"/>
<rect key="frame" x="0.0" y="0.0" width="296" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="Rrg-wr-8eL">
<font key="font" metaFont="system"/>
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="33q-UT-ur5" name="value" keyPath="objectValue.title" id="JQR-UW-ifh"/>
</connections>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="Pep-mX-LHY" id="hUe-cf-6vq"/>
</connections>
</tableCellView>
<tableCellView identifier="ItemView" id="yGq-lc-RCM" customClass="TablePathView">
<rect key="frame" x="1" y="41" width="304" height="27"/>
<tableCellView identifier="ItemView" translatesAutoresizingMaskIntoConstraints="NO" id="yGq-lc-RCM" customClass="PathTableCellView">
<rect key="frame" x="1" y="21" width="296" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<pathControl focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="f7R-TO-fmF">
<rect key="frame" x="0.0" y="1" width="251" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<rect key="frame" x="20" y="0.0" width="244" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<pathCell key="cell" controlSize="small" selectable="YES" editable="YES" focusRingType="none" alignment="left" pathStyle="popUp" id="dcz-8y-tKb">
<font key="font" metaFont="smallSystem"/>
</pathCell>
<connections>
<action selector="pathAction:" target="-2" id="4oX-bW-ANp"/>
<binding destination="yGq-lc-RCM" name="value" keyPath="objectValue.url" id="Ony-ph-VVo"/>
<binding destination="yGq-lc-RCM" name="enabled" keyPath="objectValue.valid" id="f8P-gt-vmK"/>
</connections>
</pathControl>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zNo-ij-mUl">
<rect key="frame" x="256" y="5" width="23" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" bezelStyle="rounded" image="NSNavEjectButton.normalSelected" imagePosition="overlaps" alignment="center" controlSize="small" imageScaling="proportionallyDown" inset="2" id="IZA-Tu-olu">
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="6g1-NT-J1w">
<rect key="frame" x="0.0" y="1" width="20" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageAlignment="left" image="drag-handle-4x10" id="x7F-qD-5y9"/>
</imageView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zNo-ij-mUl" customClass="EjectButton">
<rect key="frame" x="277" y="3" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="eject-16x16" imagePosition="only" alignment="center" alternateImage="eject-hover-16x16" imageScaling="proportionallyDown" inset="2" id="IZA-Tu-olu">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="deleteAction:" target="-2" id="XAl-eQ-nUj"/>
<action selector="ejectAction:" target="-2" id="XAl-eQ-nUj"/>
<binding destination="yGq-lc-RCM" name="enabled" keyPath="objectValue.occupied" id="4a4-L7-ztC"/>
</connections>
</button>
</subviews>
<connections>
<outlet property="deleteButton" destination="zNo-ij-mUl" id="9br-3c-ddI"/>
<outlet property="dragHandle" destination="6g1-NT-J1w" id="odc-Sw-3WS"/>
<outlet property="ejectButton" destination="zNo-ij-mUl" id="uzY-tA-5Wf"/>
<outlet property="pathControl" destination="f7R-TO-fmF" id="oH7-N3-JC7"/>
</connections>
</tableCellView>
<tableCellView identifier="BBItemView" id="2Nq-Xz-tkV" customClass="PathTableCellView">
<rect key="frame" x="1" y="46" width="296" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="47E-Ef-Ott">
<rect key="frame" x="0.0" y="1" width="20" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageAlignment="left" image="drag-handle-4x10" id="vwE-Ev-NBf"/>
</imageView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zxn-1E-o34" customClass="EjectButton">
<rect key="frame" x="277" y="3" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="eject-16x16" imagePosition="only" alignment="center" alternateImage="eject-hover-16x16" imageScaling="proportionallyDown" inset="2" id="Os7-NH-tnx">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="ejectAction:" target="-2" id="uy2-92-9La"/>
<binding destination="2Nq-Xz-tkV" name="enabled" keyPath="objectValue.occupied" id="SNi-sQ-J2W"/>
</connections>
</button>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pNE-yJ-EK8">
<rect key="frame" x="20" y="0.0" width="244" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="socket.address:port or /path/to/file" drawsBackground="YES" id="h2U-ig-Cms">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="textAction:" target="-2" id="lmX-t8-mEc"/>
<binding destination="2Nq-Xz-tkV" name="value" keyPath="objectValue.string" id="2dZ-JJ-asM">
<dictionary key="options">
<string key="NSNullPlaceholder">socket.address:port or /path/to/file</string>
</dictionary>
</binding>
<binding destination="2Nq-Xz-tkV" name="enabled" keyPath="objectValue.valid" id="ZTM-E3-Y9P"/>
</connections>
</textField>
</subviews>
<connections>
<outlet property="dragHandle" destination="47E-Ef-Ott" id="bnY-rz-24V"/>
<outlet property="ejectButton" destination="zxn-1E-o34" id="eC6-Mf-tN6"/>
</connections>
</tableCellView>
<tableCellView identifier="OutputItemView" id="jQd-Ar-5uf" customClass="PathTableCellView">
<rect key="frame" x="1" y="71" width="296" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="Jg1-Wh-HDk">
<rect key="frame" x="0.0" y="1" width="20" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageAlignment="left" image="drag-handle-4x10" id="SjY-iM-xSZ"/>
</imageView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vG4-PP-efF" customClass="EjectButton">
<rect key="frame" x="277" y="3" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="eject-16x16" imagePosition="only" alignment="center" alternateImage="eject-hover-16x16" imageScaling="proportionallyDown" inset="2" id="VX6-hb-mCU">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="ejectAction:" target="-2" id="LNr-rK-kpx"/>
<binding destination="jQd-Ar-5uf" name="enabled" keyPath="objectValue.occupied" id="p4S-6q-dCG"/>
</connections>
</button>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Tm9-Zq-fag">
<rect key="frame" x="20" y="0.0" width="244" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="/path/to/file" drawsBackground="YES" id="RUQ-s4-75A">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="textAction:" target="-2" id="N7h-6y-D8W"/>
<binding destination="jQd-Ar-5uf" name="value" keyPath="objectValue.string" id="kXU-qJ-HKa">
<dictionary key="options">
<string key="NSNullPlaceholder">/path/to/file</string>
</dictionary>
</binding>
<binding destination="jQd-Ar-5uf" name="enabled" keyPath="objectValue.valid" id="1wE-NY-Vb2"/>
</connections>
</textField>
</subviews>
<connections>
<outlet property="dragHandle" destination="Jg1-Wh-HDk" id="o14-ay-0Ou"/>
<outlet property="ejectButton" destination="vG4-PP-efF" id="X2I-2N-t5r"/>
</connections>
</tableCellView>
<tableCellView identifier="MidiItemView" id="HDi-YM-iKn" customClass="MidiTableCellView">
<rect key="frame" x="1" y="96" width="296" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="XcO-0S-W4c">
<rect key="frame" x="0.0" y="1" width="20" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageAlignment="left" image="drag-handle-4x10" id="4a2-So-rxD"/>
</imageView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="F3v-8Z-LaF" customClass="EjectButton">
<rect key="frame" x="277" y="3" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="eject-16x16" imagePosition="only" alignment="center" alternateImage="eject-hover-16x16" imageScaling="proportionallyDown" inset="2" id="b3t-Zp-2si">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="ejectAction:" target="-2" id="AvU-Sz-QKJ"/>
<binding destination="HDi-YM-iKn" name="enabled" keyPath="objectValue.occupied" id="ERy-Iz-T9Q"/>
</connections>
</button>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="L2F-mj-lkr">
<rect key="frame" x="20" y="-3" width="244" height="25"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="CaJ-NG-vbR" id="Rac-za-bEQ">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<menu key="menu" id="I55-5S-oM2">
<items>
<menuItem state="on" id="CaJ-NG-vbR">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="midiAction:" target="-2" id="LDL-4h-xUR"/>
<binding destination="HDi-YM-iKn" name="selectedValue" keyPath="objectValue.string" id="xjL-hx-VG3">
<dictionary key="options">
<string key="NSValueTransformerName">EmptyStringTransformer</string>
</dictionary>
</binding>
</connections>
</popUpButton>
</subviews>
<connections>
<outlet property="dragHandle" destination="XcO-0S-W4c" id="oKY-UF-LkW"/>
<outlet property="ejectButton" destination="F3v-8Z-LaF" id="ql8-4u-qCA"/>
<outlet property="popUpButton" destination="L2F-mj-lkr" id="Ktx-Yc-DIp"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
@ -117,20 +251,27 @@
</connections>
</outlineView>
</subviews>
<nil key="backgroundColor"/>
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="9Vz-lW-4GG">
<rect key="frame" x="-100" y="-100" width="306" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="f8l-nC-KhG">
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="f8l-nC-KhG" customClass="TransparentScroller">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
<color key="value" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</scroller>
<point key="canvasLocation" x="-161" y="55"/>
<point key="canvasLocation" x="-161" y="54.5"/>
</scrollView>
</objects>
<resources>
<image name="NSNavEjectButton.normalSelected" width="16" height="16"/>
<image name="drag-handle-4x10" width="4" height="10"/>
<image name="eject-16x16" width="8" height="9"/>
<image name="eject-hover-16x16" width="16" height="16"/>
</resources>
</document>

View File

@ -8,7 +8,9 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PreferencesWindowController">
<connections>
<outlet property="fixButton" destination="kt8-xs-My0" id="GeF-Kj-q2l"/>
<outlet property="pathField" destination="Oz5-Xb-btk" id="EnV-kr-0XI"/>
<outlet property="wdField" destination="l8V-pC-gml" id="exX-bU-pbh"/>
<outlet property="window" destination="QvC-M9-y7g" id="xJa-tx-X62"/>
</connections>
</customObject>
@ -24,7 +26,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Oz5-Xb-btk">
<rect key="frame" x="98" y="181" width="362" height="21"/>
<rect key="frame" x="138" y="159" width="322" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="vDR-2V-qxd">
<font key="font" usesAppearanceFont="YES"/>
@ -33,21 +35,35 @@
</textFieldCell>
<connections>
<action selector="pathChanged:" target="-2" id="RRj-dC-q2y"/>
<binding destination="yvB-HG-64y" name="enabled" keyPath="values.UseCustomMame" id="iex-A9-Db6"/>
<binding destination="yvB-HG-64y" name="value" keyPath="values.MamePath" id="H3O-1l-peo"/>
<binding destination="yvB-HG-64y" name="enabled" keyPath="values.UseCustomMame" id="iex-A9-Db6"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Qmb-Ag-Xyr">
<rect key="frame" x="18" y="184" width="74" height="16"/>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l8V-pC-gml">
<rect key="frame" x="138" y="128" width="322" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="wfj-GY-Qu2">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="wdChanged:" target="-2" id="g1P-8l-ZXi"/>
<binding destination="yvB-HG-64y" name="value" keyPath="values.MameWorkingDirectory" id="Kc9-Pc-XGU"/>
<binding destination="yvB-HG-64y" name="enabled" keyPath="values.UseCustomMame" id="DeG-OW-Gd2"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vTJ-Ez-c1R">
<rect key="frame" x="18" y="131" width="114" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="MAME Path" id="Xcq-4g-Wlw">
<textFieldCell key="cell" lineBreakMode="clipping" title="Working Directory" id="UHt-0s-zxA">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KAN-P2-ydI">
<rect key="frame" x="96" y="234" width="217" height="18"/>
<rect key="frame" x="136" y="212" width="217" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Close log window on normal exit" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="QMz-O0-06U">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@ -58,7 +74,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="j7D-jC-17Q">
<rect key="frame" x="96" y="208" width="139" height="18"/>
<rect key="frame" x="136" y="186" width="139" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Use Custom MAME" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="V61-mz-QFo">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@ -68,9 +84,40 @@
<binding destination="yvB-HG-64y" name="value" keyPath="values.UseCustomMame" id="lH4-dm-kQC"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kt8-xs-My0">
<rect key="frame" x="287" y="13" width="179" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="push" title="Fix VMNet Permissions" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ifc-ID-wbu">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="fixPerms:" target="-2" id="0e2-yf-UgY"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Qmb-Ag-Xyr">
<rect key="frame" x="58" y="162" width="74" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="MAME Path" id="Xcq-4g-Wlw">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qT7-cc-Phc">
<rect key="frame" x="136" y="234" width="118" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Use log window" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Adv-KH-abG">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="yvB-HG-64y" name="value" keyPath="values.UseLogWindow" id="meK-Jb-s8b"/>
</connections>
</button>
</subviews>
</view>
<point key="canvasLocation" x="140" y="147"/>
<point key="canvasLocation" x="80" y="144"/>
</window>
<userDefaultsController id="KVS-Ag-1un"/>
<userDefaultsController representsSharedInstance="YES" id="yvB-HG-64y"/>

View File

@ -8,625 +8,229 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SlotViewController">
<connections>
<outlet property="aux_menu" destination="3kq-qn-7YR" id="wic-Ry-yAf"/>
<outlet property="exp_menu" destination="San-wP-1ez" id="X7u-dM-xrI"/>
<outlet property="game_menu" destination="K8G-bZ-6mZ" id="IeQ-ZT-5F6"/>
<outlet property="modem_menu" destination="KHf-kC-BpZ" id="Qab-mA-anC"/>
<outlet property="printer_menu" destination="sTp-en-8Wd" id="zeu-LF-6mV"/>
<outlet property="ram_menu" destination="Yks-M5-vi0" id="h5y-Un-jYJ"/>
<outlet property="rs232_menu" destination="6ln-U2-0Pi" id="7CT-OE-idV"/>
<outlet property="sl0_menu" destination="Jw1-t7-YyU" id="BB5-6y-zyf"/>
<outlet property="sl1_menu" destination="bta-RS-JT4" id="cpI-db-kzX"/>
<outlet property="sl2_menu" destination="cDU-b1-x5a" id="WtL-Fo-Q1B"/>
<outlet property="sl3_menu" destination="aSh-cs-0Nn" id="24o-66-LjH"/>
<outlet property="sl4_menu" destination="kU5-cR-hPZ" id="STc-6r-nxH"/>
<outlet property="sl5_menu" destination="8z4-8f-kLU" id="cLl-Ee-LUD"/>
<outlet property="sl6_menu" destination="GLb-F4-PWe" id="ubk-pt-e1Q"/>
<outlet property="sl7_menu" destination="IV2-3M-qfw" id="s5k-4G-w4r"/>
<outlet property="view" destination="OM3-7F-wiN" id="yre-ts-aHj"/>
<outlet property="_popover" destination="QIT-2T-wdy" id="WUB-OS-kem"/>
<outlet property="childOutlineView" destination="uM0-Gk-crn" id="aL5-uC-O28"/>
<outlet property="outlineView" destination="Xj3-Qf-yek" id="AWE-Rg-XUM"/>
<outlet property="view" destination="D45-lv-6Fv" id="av3-OE-ph2"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<gridView autoresizesSubviews="NO" xPlacement="leading" yPlacement="bottom" rowAlignment="none" translatesAutoresizingMaskIntoConstraints="NO" id="OM3-7F-wiN">
<rect key="frame" x="0.0" y="0.0" width="306" height="534"/>
<rows>
<gridRow yPlacement="center" height="30" id="tHD-ui-hIL">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.ram" id="ze9-jx-lv0">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="Ccd-U2-Gx5">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.sl0" id="YsR-kI-yrh">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="JGU-aq-3uw">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.sl1" id="1io-aZ-v2G">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="gVW-Ya-phU">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.sl2" id="AgS-hm-ePr">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="3fP-qp-zmi">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.sl3" id="98U-4P-iRh">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="86u-5p-UT6">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.sl4" id="hsy-pm-Qjk">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="Wdg-xb-xQx">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.sl5" id="0QC-RB-278">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="ein-Fe-vBw">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.sl6" id="731-3P-DUy">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="qjB-2w-AWE">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.sl7" id="sew-Ds-4I9">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="EEX-dh-jwn">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.exp" id="EOZ-lS-QHF">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="OaZ-ZQ-gKK">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.aux" id="OlF-v7-JZx">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="wQi-Oz-7Ye">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.rs232" id="AeP-bn-blv">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="gr2-eY-995">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.gameio" id="x3I-Bd-9di">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="1xN-lm-s4l">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.printer" id="T9a-lH-z5K">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
<gridRow yPlacement="center" height="30" id="M2s-qn-SIT">
<connections>
<binding destination="-2" name="hidden" keyPath="machine.modem" id="PSe-R3-S3e">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</gridRow>
</rows>
<columns>
<gridColumn xPlacement="fill" width="100" id="zpB-Rf-dWg"/>
<gridColumn xPlacement="fill" width="200" id="6Vn-yh-FoQ"/>
</columns>
<gridCells>
<gridCell row="tHD-ui-hIL" column="zpB-Rf-dWg" id="deJ-sv-Hb7">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nHa-QG-HjJ">
<rect key="frame" x="-2" y="511" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="RAM:" id="CvY-8m-Ni9">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="tHD-ui-hIL" column="6Vn-yh-FoQ" id="dak-Ha-01u">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="16" translatesAutoresizingMaskIntoConstraints="NO" id="Yks-M5-vi0">
<rect key="frame" x="104" y="506" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="92u-m2-3yN" id="XFo-KF-ueS">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="k8O-sG-Qld">
<items>
<menuItem title="Item 1" state="on" id="92u-m2-3yN">
<attributedString key="attributedTitle"/>
</menuItem>
<menuItem title="Item 2" id="dPG-tR-M4A"/>
<menuItem title="Item 3" id="q2n-oZ-46s"/>
</items>
</menu>
</popUpButtonCell>
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="27" horizontalPageScroll="10" verticalLineScroll="27" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" id="D45-lv-6Fv">
<rect key="frame" x="0.0" y="0.0" width="316" height="386"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" autoresizesSubviews="NO" focusRingType="none" drawsBackground="NO" copiesOnScroll="NO" id="8x1-xN-a7c">
<rect key="frame" x="0.0" y="0.0" width="316" height="386"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" selectionHighlightStyle="none" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="25" rowSizeStyle="automatic" viewBased="YES" indentationPerLevel="2" autoresizesOutlineColumn="YES" outlineTableColumn="u7T-p8-F2Z" id="Xj3-Qf-yek">
<rect key="frame" x="0.0" y="0.0" width="316" height="386"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" white="1" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn editable="NO" width="296" minWidth="40" maxWidth="1000" id="u7T-p8-F2Z">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="FM7-eO-FE4">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews>
<tableCellView identifier="MenuCell" id="1RI-9K-5qj" customClass="SlotTableCellView">
<rect key="frame" x="1" y="1" width="296" height="25"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qIF-d4-kOf">
<rect key="frame" x="0.0" y="5" width="90" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="RAM:" id="tIz-xZ-ZJH">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zQ8-o3-yBB">
<rect key="frame" x="82" y="0.0" width="199" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" selectedItem="tGi-yg-GFr" id="gt4-HK-pd1">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" autoenablesItems="NO" id="KWV-nn-eiB">
<items>
<menuItem title="Item 1" state="on" id="tGi-yg-GFr"/>
<menuItem title="Item 2" id="XJr-Gb-4D4"/>
<menuItem title="Item 3" id="JeB-Fb-DeQ"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="9MH-mu-u5V"/>
</connections>
</popUpButton>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xCe-sY-sGe">
<rect key="frame" x="282" y="8" width="14" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="NSListViewTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyUpOrDown" inset="2" id="0qU-ID-kJ8">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="hamburger:" target="-2" id="5Xa-j7-Aod"/>
<binding destination="1RI-9K-5qj" name="hidden" keyPath="objectValue.selectedItem.children" id="rY2-0l-0N8">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNil</string>
</dictionary>
</binding>
</connections>
</button>
</subviews>
<connections>
<outlet property="hamburgerButton" destination="xCe-sY-sGe" id="5Da-If-Bt4"/>
<outlet property="menuButton" destination="zQ8-o3-yBB" id="zZf-nm-tCI"/>
<outlet property="textField" destination="qIF-d4-kOf" id="zIF-4n-v1e"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<action selector="memoryMenuChanged:" target="-2" id="m1Q-Xj-z22"/>
<binding destination="-2" name="content" keyPath="machine.ram" id="UCD-j5-7Bh"/>
<outlet property="dataSource" destination="-2" id="OV9-yE-OFp"/>
<outlet property="delegate" destination="-2" id="kXs-TN-3VL"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="Ccd-U2-Gx5" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="QI6-Cz-URX">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="v8c-Rp-Mnt">
<rect key="frame" x="-2" y="475" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Slot 0:" id="EF7-NX-RMW">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="Ccd-U2-Gx5" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="0KQ-Qt-8KP">
<popUpButton key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Jw1-t7-YyU">
<rect key="frame" x="104" y="470" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="8Iv-mH-mEI" id="47g-IO-4Xt">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="nrR-Tr-UaW">
<items>
<menuItem title="Item 1" state="on" id="8Iv-mH-mEI"/>
<menuItem title="Item 2" id="Prr-6W-NWp"/>
<menuItem title="Item 3" id="xz3-bi-5IM"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="wPZ-cY-9Ir"/>
<binding destination="-2" name="content" keyPath="machine.sl0" id="2aW-3q-Mvt"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="JGU-aq-3uw" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="Y1R-Ob-g2b">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0gP-wH-DVr">
<rect key="frame" x="-2" y="439" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Slot 1:" id="bfg-tf-E34">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="JGU-aq-3uw" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="v8q-Rj-E4q">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="1" translatesAutoresizingMaskIntoConstraints="NO" id="bta-RS-JT4">
<rect key="frame" x="104" y="434" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="dXO-at-nGw" id="kNn-6b-ysf">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="4ah-BI-RD5">
<items>
<menuItem title="Item 1" state="on" id="dXO-at-nGw"/>
<menuItem title="Item 2" id="UZY-8b-qmE"/>
<menuItem title="Item 3" id="zxA-OM-BIY"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="hl3-N2-89k"/>
<binding destination="-2" name="content" keyPath="machine.sl1" id="wQI-oy-SYz"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="gVW-Ya-phU" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="tpv-Yc-qii">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="EHZ-ol-QVz">
<rect key="frame" x="-2" y="403" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Slot 2:" id="FlL-pN-rn7">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="gVW-Ya-phU" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="OzN-rM-Pgi">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="2" translatesAutoresizingMaskIntoConstraints="NO" id="cDU-b1-x5a">
<rect key="frame" x="104" y="398" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="vCY-qF-aB3" id="jvL-SH-nvG">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="Hp6-Gt-pVV">
<items>
<menuItem title="Item 1" state="on" id="vCY-qF-aB3"/>
<menuItem title="Item 2" id="pbR-nc-itb"/>
<menuItem title="Item 3" id="L8Z-vH-OCa"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="T5w-C4-Ohq"/>
<binding destination="-2" name="content" keyPath="machine.sl2" id="uXQ-0A-98q"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="3fP-qp-zmi" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="LbW-TT-AQ7">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zGs-8d-L0S">
<rect key="frame" x="-2" y="367" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Slot 3:" id="KZK-h8-8cw">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="3fP-qp-zmi" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="h8H-TB-p2z">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="3" translatesAutoresizingMaskIntoConstraints="NO" id="aSh-cs-0Nn">
<rect key="frame" x="104" y="362" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="2yS-4z-8OR" id="HaE-TD-5Wx">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="zka-z5-hPa">
<items>
<menuItem title="Item 1" state="on" id="2yS-4z-8OR"/>
<menuItem title="Item 2" id="q4H-Fz-zVr"/>
<menuItem title="Item 3" id="HtQ-6y-S25"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="5uS-La-5cM"/>
<binding destination="-2" name="content" keyPath="machine.sl3" id="YgU-fX-fPC"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="86u-5p-UT6" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="hJR-nJ-yYi">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zsX-jd-6ba">
<rect key="frame" x="-2" y="331" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Slot 4:" id="WXv-RF-e7f">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="86u-5p-UT6" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="dHu-cL-FyO">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="4" translatesAutoresizingMaskIntoConstraints="NO" id="kU5-cR-hPZ">
<rect key="frame" x="104" y="326" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="NaS-CV-XQm" id="rOP-eY-UKe">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="Iwv-z3-oJb">
<items>
<menuItem title="Item 1" state="on" id="NaS-CV-XQm"/>
<menuItem title="Item 2" id="ovb-SG-Eg4"/>
<menuItem title="Item 3" id="GVh-L4-3Cp"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="I35-wl-YdH"/>
<binding destination="-2" name="content" keyPath="machine.sl4" id="yfx-hj-6Ly"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="Wdg-xb-xQx" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="dsM-t5-8ng">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ANg-c1-hGf">
<rect key="frame" x="-2" y="295" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Slot 5:" id="EhN-EV-65V">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="Wdg-xb-xQx" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="ffm-pA-jjo">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="5" translatesAutoresizingMaskIntoConstraints="NO" id="8z4-8f-kLU">
<rect key="frame" x="104" y="290" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="gH7-4J-xsg" id="cmc-Gf-Slp">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="Cma-00-qCY">
<items>
<menuItem title="Item 1" state="on" id="gH7-4J-xsg"/>
<menuItem title="Item 2" id="meM-WH-GgP"/>
<menuItem title="Item 3" id="ILg-Ld-9Ri"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="jSe-j9-QUW"/>
<binding destination="-2" name="content" keyPath="machine.sl5" id="Uo1-Rg-wko"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="ein-Fe-vBw" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="PSw-Jx-eS2">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Cr1-RK-Z7V">
<rect key="frame" x="-2" y="259" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Slot 6:" id="uzy-th-5Yc">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="ein-Fe-vBw" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="FsV-vO-KAs">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="6" translatesAutoresizingMaskIntoConstraints="NO" id="GLb-F4-PWe">
<rect key="frame" x="104" y="254" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="VaX-M9-Op0" id="CjU-rC-HUT">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="3xq-Hn-icN">
<items>
<menuItem title="Item 1" state="on" id="VaX-M9-Op0"/>
<menuItem title="Item 2" id="Fhy-5D-e6z"/>
<menuItem title="Item 3" id="9jw-LA-666"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="yZO-kH-P6Q"/>
<binding destination="-2" name="content" keyPath="machine.sl6" id="0ze-xJ-DNX"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="qjB-2w-AWE" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="1WE-Mm-0O3">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3Ia-XB-C6D">
<rect key="frame" x="-2" y="223" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Slot 7:" id="32J-6e-nRV">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="qjB-2w-AWE" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="Yvr-uR-Hr5">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="7" translatesAutoresizingMaskIntoConstraints="NO" id="IV2-3M-qfw">
<rect key="frame" x="104" y="218" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="8nb-Bq-4R4" id="nKb-Ar-bCb">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="R2a-Mg-LsY">
<items>
<menuItem title="Item 1" state="on" id="8nb-Bq-4R4"/>
<menuItem title="Item 2" id="rFT-bC-KE9"/>
<menuItem title="Item 3" id="4jB-gp-lYT"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="llh-ab-ayK"/>
<binding destination="-2" name="content" keyPath="machine.sl7" id="hT6-pS-WmL"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="EEX-dh-jwn" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="iRl-IX-FSD">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Avf-lX-f2Q">
<rect key="frame" x="-2" y="187" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Expansion:" id="PEU-OV-910">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="EEX-dh-jwn" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="Ehv-aA-Llc">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="8" translatesAutoresizingMaskIntoConstraints="NO" id="San-wP-1ez">
<rect key="frame" x="104" y="182" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="jtv-Qx-oVD" id="42u-b4-3kx">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="1hM-MS-UEz">
<items>
<menuItem title="Item 1" state="on" id="jtv-Qx-oVD"/>
<menuItem title="Item 2" id="UeB-A1-nyv"/>
<menuItem title="Item 3" id="GyZ-dv-MS4"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="fi5-WL-lQa"/>
<binding destination="-2" name="content" keyPath="machine.exp" id="C88-Gb-QTE"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="OaZ-ZQ-gKK" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="wRB-Wh-7kG">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="EMz-7i-H38">
<rect key="frame" x="-2" y="151" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Auxiliary:" id="SoV-Qy-h2g">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="OaZ-ZQ-gKK" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="bx6-Rc-x2V">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="3kq-qn-7YR">
<rect key="frame" x="104" y="146" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="vWX-Cb-ldP" id="NqP-Uq-Knv">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="7Ef-KS-ulj">
<items>
<menuItem title="Item 1" state="on" id="vWX-Cb-ldP"/>
<menuItem title="Item 2" id="Yg1-xZ-vXq"/>
<menuItem title="Item 3" id="BwC-w9-hBy"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="uvt-uD-Adn"/>
<binding destination="-2" name="content" keyPath="machine.aux" id="KA7-7x-qeJ"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="wQi-Oz-7Ye" column="zpB-Rf-dWg" xPlacement="fill" yPlacement="center" id="KoQ-xV-fQu">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JAG-sJ-u2B">
<rect key="frame" x="-2" y="115" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="RS 232:" id="iG2-rY-VDv">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="wQi-Oz-7Ye" column="6Vn-yh-FoQ" xPlacement="fill" yPlacement="center" id="zWk-jd-i0V">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="10" translatesAutoresizingMaskIntoConstraints="NO" id="6ln-U2-0Pi">
<rect key="frame" x="104" y="110" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="uu3-rr-iD8" id="daT-eX-4Vu">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="fMw-mh-Qfi">
<items>
<menuItem title="Item 1" state="on" id="uu3-rr-iD8"/>
<menuItem title="Item 2" id="f1r-MS-itp"/>
<menuItem title="Item 3" id="WhP-Di-CHP"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="gmZ-pW-35n"/>
<binding destination="-2" name="content" keyPath="machine.rs232" id="LxA-8b-jb4"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="gr2-eY-995" column="zpB-Rf-dWg" id="xIE-bJ-mzr">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Svb-pu-WPf">
<rect key="frame" x="-2" y="79" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Game I/O:" id="2Gc-mV-zCZ">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="gr2-eY-995" column="6Vn-yh-FoQ" id="nhy-Gp-GLL">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="11" translatesAutoresizingMaskIntoConstraints="NO" id="K8G-bZ-6mZ">
<rect key="frame" x="104" y="74" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="GOm-Tf-6qc" id="Mig-Nu-gZB">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="faU-zS-LgN">
<items>
<menuItem title="Item 1" state="on" id="GOm-Tf-6qc"/>
<menuItem title="Item 2" id="XgG-U0-2G7"/>
<menuItem title="Item 3" id="4Ea-aE-sB1"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="o53-71-xuf"/>
<binding destination="-2" name="content" keyPath="machine.gameio" id="tJw-AS-RUz"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="1xN-lm-s4l" column="zpB-Rf-dWg" id="vPV-KN-NNp">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="31K-iE-RCe">
<rect key="frame" x="-2" y="43" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Printer:" id="QZI-H7-i8m">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="1xN-lm-s4l" column="6Vn-yh-FoQ" id="KRc-Z8-drK">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="12" translatesAutoresizingMaskIntoConstraints="NO" id="sTp-en-8Wd">
<rect key="frame" x="104" y="38" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="TU9-ed-ofw" id="1OL-aw-xNL">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="MSP-Iu-ix3">
<items>
<menuItem title="Item 1" state="on" id="TU9-ed-ofw"/>
<menuItem title="Item 2" id="7wI-Tn-rE0"/>
<menuItem title="Item 3" id="bQc-pc-ccM"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="Fxc-YB-SF9"/>
<binding destination="-2" name="content" keyPath="machine.printer" id="3l1-Hn-v47"/>
</connections>
</popUpButton>
</gridCell>
<gridCell row="M2s-qn-SIT" column="zpB-Rf-dWg" id="8R2-aA-mLq">
<textField key="contentView" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MH0-Nk-5Py">
<rect key="frame" x="-2" y="7" width="104" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Modem:" id="HQq-VN-Ju9">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="M2s-qn-SIT" column="6Vn-yh-FoQ" id="idI-pW-e7v">
<popUpButton key="contentView" verticalHuggingPriority="750" tag="13" translatesAutoresizingMaskIntoConstraints="NO" id="KHf-kC-BpZ">
<rect key="frame" x="104" y="2" width="205" height="25"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="CxO-3g-va1" id="jDr-6p-C7y">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="lxi-Z0-ya6">
<items>
<menuItem title="Item 1" state="on" id="CxO-3g-va1"/>
<menuItem title="Item 2" id="OpR-vy-iL5"/>
<menuItem title="Item 3" id="xvH-9B-ge5"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="pHW-GG-2VQ"/>
<binding destination="-2" name="content" keyPath="machine.modem" id="hFa-pj-NnN"/>
</connections>
</popUpButton>
</gridCell>
</gridCells>
<point key="canvasLocation" x="268" y="71"/>
</gridView>
<userDefaultsController representsSharedInstance="YES" id="ZGN-Cx-9po"/>
</outlineView>
</subviews>
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="rYF-ld-adB">
<rect key="frame" x="-100" y="-100" width="223" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="4pL-Dn-e75" customClass="TransparentScroller">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
<color key="value" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</scroller>
<point key="canvasLocation" x="-100" y="154"/>
</scrollView>
<viewController id="ziL-Zf-s1k" userLabel="Popover View Controller">
<connections>
<outlet property="view" destination="uew-UQ-Q25" id="qjB-ya-gFf"/>
</connections>
</viewController>
<popover behavior="t" id="QIT-2T-wdy">
<connections>
<outlet property="contentViewController" destination="ziL-Zf-s1k" id="rj8-2U-9t0"/>
</connections>
</popover>
<customView id="uew-UQ-Q25">
<rect key="frame" x="0.0" y="0.0" width="250" height="400"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button id="2jh-iq-DV6">
<rect key="frame" x="232" y="382" width="14" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="NSStopProgressFreestandingTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyUpOrDown" inset="2" id="Wp7-Km-kYI">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell>
<connections>
<action selector="performClose:" target="QIT-2T-wdy" id="Q04-24-ZOK"/>
</connections>
</button>
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="27" horizontalPageScroll="10" verticalLineScroll="27" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" id="5gB-oE-Gza">
<rect key="frame" x="0.0" y="20" width="250" height="360"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" focusRingType="none" drawsBackground="NO" copiesOnScroll="NO" id="X5e-Ka-JLr">
<rect key="frame" x="0.0" y="0.0" width="250" height="360"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" selectionHighlightStyle="none" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="25" rowSizeStyle="automatic" viewBased="YES" indentationPerLevel="16" autoresizesOutlineColumn="YES" outlineTableColumn="o1K-z1-KVi" id="uM0-Gk-crn">
<rect key="frame" x="0.0" y="0.0" width="250" height="360"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" white="1" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="230" minWidth="40" maxWidth="1000" id="o1K-z1-KVi">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="A12-NQ-gW3">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews>
<tableCellView identifier="MenuCell" id="Mgb-8H-DmI" customClass="SlotTableCellView">
<rect key="frame" x="1" y="1" width="230" height="25"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ThL-Yz-7Kd">
<rect key="frame" x="1" y="0.0" width="229" height="25"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" selectedItem="djR-rV-wzX" id="SkW-fW-gwL">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" autoenablesItems="NO" id="7Ib-TL-f6U">
<items>
<menuItem title="Item 1" state="on" id="djR-rV-wzX"/>
<menuItem title="Item 2" id="qbC-4D-6t6"/>
<menuItem title="Item 3" id="qPv-x5-zpj"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="menuChanged:" target="-2" id="ytA-nD-fIS"/>
</connections>
</popUpButton>
</subviews>
<connections>
<outlet property="menuButton" destination="ThL-Yz-7Kd" id="3Oc-hx-qKl"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<outlet property="dataSource" destination="-2" id="HXP-pH-3Lc"/>
<outlet property="delegate" destination="-2" id="nwb-IL-MsP"/>
</connections>
</outlineView>
</subviews>
<color key="backgroundColor" white="1" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="Keh-oo-CPO">
<rect key="frame" x="-100" y="-100" width="223" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="wtc-gL-alh" customClass="TransparentScroller">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
<point key="canvasLocation" x="-451" y="61"/>
</customView>
</objects>
<resources>
<image name="NSListViewTemplate" width="14" height="10"/>
<image name="NSStopProgressFreestandingTemplate" width="14" height="14"/>
</resources>
</document>

14
Ample/Bookmark.h Normal file
View File

@ -0,0 +1,14 @@
//
// Bookmark.h
// Ample
//
// Created by Kelvin Sherlock on 2/7/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
#ifndef Bookmark_h
#define Bookmark_h
#import "Bookmark+CoreDataClass.h"
#endif /* Bookmark_h */

45
Ample/BookmarkManager.h Normal file
View File

@ -0,0 +1,45 @@
//
// BookmarkManager.h
// Ample
//
// Created by Kelvin Sherlock on 6/1/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@class NSMenu;
@class NSMenuItem;
@class Bookmark;
@class DiskImage;
NS_ASSUME_NONNULL_BEGIN
@interface BookmarkManager : NSObject
@property (weak) IBOutlet NSMenu *menu;
@property (weak) IBOutlet NSMenuItem *updateMenuItem;
@property (readonly) NSManagedObjectContext *managedObjectContext;
@property (nullable) Bookmark *currentBookmark;
+(instancetype)sharedManager;
-(NSString *)uniqueBookmarkName: (NSString *)name;
-(NSError *)saveBookmark: (NSDictionary *)bookmark name: (NSString *)name automatic: (BOOL)automatic;
//-(NSError *)saveDefault: (NSDictionary *)bookmark;
-(Bookmark *)defaultBookmark;
-(NSDictionary *)loadDefault;
-(NSError *)setAutomatic: (Bookmark *)bookmark;
-(BOOL)addDiskImage: (NSObject *)pathOrURL;
//-(void)convertLegacyBookmarks;
@end
NS_ASSUME_NONNULL_END

651
Ample/BookmarkManager.m Normal file
View File

@ -0,0 +1,651 @@
//
// BookmarkManager.m
// Ample
//
// Created by Kelvin Sherlock on 6/1/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import "BookmarkManager.h"
#import "Ample.h"
#import "Bookmark.h"
#import "DiskImage.h"
#import "Menu.h"
@interface BookmarkManager () {
NSPersistentStoreCoordinator *_psc;
NSManagedObjectContext *_moc;
NSManagedObjectModel *_mom;
NSPersistentStore *_store;
NSFetchRequest *_defaultRequest;
NSURL *_bookmarkDirectory;
NSArrayController *_items;
NSUInteger _newMenuGeneration;
NSUInteger _currentMenuGeneration;
Bookmark *_currentBookmark;
}
@end
@interface BookmarkManager (MenuDelegate) <NSMenuDelegate>
@end
@implementation BookmarkManager
static BookmarkManager *singleton = nil;
-(void)awakeFromNib {
if (!singleton) {
singleton = self;
if (!_items) [self initMenus];
}
}
+(instancetype)sharedManager {
if (!singleton) singleton = [BookmarkManager new];
return singleton;
}
-(instancetype)init {
if (singleton) return singleton;
if ((self = [super init])) {
[self initCoreData];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver: self selector: @selector(willTerminate:) name: NSApplicationWillTerminateNotification object: nil];
[nc addObserver: self selector: @selector(diskImageAdded:) name: kNotificationDiskImageAdded object: nil];
_newMenuGeneration = 1;
_currentMenuGeneration = 0;
}
//singleton = self;
return self;
}
-(NSManagedObjectContext *)managedObjectContext {
return _moc;
}
-(void)initCoreData {
NSError *error;
BOOL new = NO;
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource: @"Ample" withExtension: @"momd"];
_mom = [[NSManagedObjectModel alloc] initWithContentsOfURL: url];
_psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: _mom];
_moc = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSMainQueueConcurrencyType];
[_moc setPersistentStoreCoordinator: _psc];
//[_moc setMergePolicy: [NSMergePolicy rollbackMergePolicy]];
url = SupportDirectory();
#if 0
url = [url URLByAppendingPathComponent: @"Ample.db"];
if (![url checkResourceIsReachableAndReturnError: &error])
new = YES;
_store = [_psc addPersistentStoreWithType: NSSQLiteStoreType
configuration: nil
URL: url
options: nil
error: &error];
#else
url = [url URLByAppendingPathComponent: @"Ample.xml"];
if (![url checkResourceIsReachableAndReturnError: &error])
new = YES;
_store = [_psc addPersistentStoreWithType: NSXMLStoreType
configuration: nil
URL: url
options: nil
error: &error];
#endif
_defaultRequest = [Bookmark fetchRequest];
[_defaultRequest setPredicate: [NSPredicate predicateWithFormat: @"automatic == TRUE"]];
if (new) {
[self convertLegacyBookmarks];
[self convertLegacyDiskImages];
}
}
-(void)willTerminate: (NSNotification *)notification {
NSError *error;
if (![_moc save: &error]) {
NSLog(@"%@", error);
}
}
-(void)convertLegacyBookmarks {
//NSEntityDescription *e;
//e = [NSEntityDescription entityForName: @"Bookmark" inManagedObjectContext: moc];
NSURL *url = [self bookmarkDirectory];
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error = nil;
NSArray *files = [fm contentsOfDirectoryAtURL: url
includingPropertiesForKeys: nil
options: NSDirectoryEnumerationSkipsHiddenFiles
error: &error];
NSDate *now = [NSDate date];
for (NSURL *url in files) {
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfURL: url];
//NSData *data = [NSPropertyListSerialization dataWithPropertyList: dict format: NSPropertyListBinaryFormat_v1_0 options: 0 error: &error];
Bookmark *b = (Bookmark *)[NSEntityDescription insertNewObjectForEntityForName: @"Bookmark" inManagedObjectContext: _moc];
[b setName: [url lastPathComponent]];
[b setDictionary: dict];
//[b setData: data];
[b setMachine: [dict objectForKey: @"machine"]];
[b setCreated: now];
}
// default...
url = [url URLByAppendingPathComponent: @".Default"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfURL: url];
if (dict) {
//NSData *data = [NSPropertyListSerialization dataWithPropertyList: dict format: NSPropertyListBinaryFormat_v1_0 options: 0 error: &error];
NSString *name = [self uniqueBookmarkName: @"Default"];
Bookmark *b = (Bookmark *)[NSEntityDescription insertNewObjectForEntityForName: @"Bookmark" inManagedObjectContext: _moc];
[b setName: name];
[b setAutomatic: YES];
[b setDictionary: dict];
//[b setData: data];
[b setMachine: [dict objectForKey: @"machine"]];
[b setCreated: now];
}
if (![_moc save: &error]) {
NSLog(@"%@", error);
}
}
-(void)convertLegacyDiskImages {
NSError *error;
NSURL *sd = SupportDirectory();
NSURL *url = [sd URLByAppendingPathComponent: @"RecentDiskImages.plist"];
NSArray *array = [NSArray arrayWithContentsOfURL: url];
if (!array) return;
for (NSDictionary *d in array) {
NSManagedObject *o = [NSEntityDescription insertNewObjectForEntityForName: @"DiskImage" inManagedObjectContext: _moc];
[o setValue: [d objectForKey: @"date"] forKey: @"added"];
[o setValue: [d objectForKey: @"date"] forKey: @"accessed"];
[o setValue: [d objectForKey: @"path"] forKey: @"path"];
[o setValue: [d objectForKey: @"size"] forKey: @"size"];
}
if (![_moc save: &error]) {
NSLog(@"%@", error);
}
}
-(NSURL *)bookmarkDirectory {
if (_bookmarkDirectory) return _bookmarkDirectory;
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *url = SupportDirectory();
url = [url URLByAppendingPathComponent: @"Bookmarks"];
NSError *error = nil;
[fm createDirectoryAtURL: url withIntermediateDirectories: YES attributes: nil error: &error];
if (error) NSLog(@"%@", error);
_bookmarkDirectory = url;
return url;
}
-(Bookmark *)defaultBookmark {
NSFetchRequest *req;
NSError *error;
NSArray *array;
req = [Bookmark fetchRequest];
[req setPredicate: [NSPredicate predicateWithFormat: @"automatic == TRUE"]];
array = [_moc executeFetchRequest: req error: &error];
return [array firstObject];
}
-(NSDictionary *)loadDefault {
Bookmark *b = [self defaultBookmark];
return [b dictionary];
}
/* save as .Default */
-(NSError *)saveDefault: (NSDictionary *)bookmark {
return nil;
#if 0
/* check if it already exists */
NSFetchRequest *req;
NSError *error;
NSArray *array;
Bookmark *b;
NSDate *now = [NSDate date];
BOOL ok;
req = [[NSFetchRequest alloc] initWithEntityName: @"Default"];
array = [_moc executeFetchRequest: req error: &error];
b = [array firstObject];
if (b) {
[b setModified: now];
} else {
b = (Bookmark *)[NSEntityDescription insertNewObjectForEntityForName: @"Default" inManagedObjectContext: _moc];
[b setName: @"Default"];
[b setCreated: now];
}
[b setDictionary: bookmark];
[b setMachine: [bookmark objectForKey: @"machine"]];
ok = [_moc save: &error];
if (!ok) NSLog(@"%@", error);
return error;
#if 0
NSURL *url = [self bookmarkDirectory];
url = [url URLByAppendingPathComponent: @".Default"];
NSError *error = nil;
BOOL ok = NO;
if (@available(macOS 10.13, *)) {
ok = [bookmark writeToURL: url error: &error];
if (!ok) NSLog(@"%@", error);
} else {
ok = [bookmark writeToURL: url atomically: YES];
}
return ok;
#endif
#endif
}
-(NSError *)setAutomatic: (Bookmark *)bookmark {
NSError *error = nil;
NSFetchRequest *req = [Bookmark fetchRequest];
[req setPredicate: [NSPredicate predicateWithFormat: @"automatic == TRUE"]];
NSArray *array = [_moc executeFetchRequest: req error: &error];
for (Bookmark *b in array) {
if (b != bookmark) [b setAutomatic: NO];
}
[bookmark setAutomatic: YES];
if (error) return error;
[_moc save: &error];
return error;
}
-(NSError *)saveBookmark: (NSDictionary *)bookmark name: (NSString *)name automatic: (BOOL)automatic {
NSDate *now = [NSDate date];
NSError *error;
BOOL ok;
Bookmark *b = (Bookmark *)[NSEntityDescription insertNewObjectForEntityForName: @"Bookmark" inManagedObjectContext: _moc];
[b setName: name];
[b setDictionary: bookmark];
[b setMachine: [bookmark objectForKey: @"machine"]];
[b setCreated: now];
[b setAutomatic: automatic];
ok = [b validateForInsert: &error];
if (!ok) {
// will be useful, eg "name is too long"
// keys: NSValidationErrorObject, NSLocalizedDescription, NSValidationErrorKey, NSValidationErrorValue
//NSLog(@"%@", error);
[_moc deleteObject: b];
return error;
}
ok = [_moc save: &error];
if (!ok) {
//NSLog(@"%@", error);
[_moc deleteObject: b];
error = [NSError errorWithDomain: @"Ample" code: 0 userInfo: @{ NSLocalizedDescriptionKey: @"Duplicate name" }];
return error;
}
if (automatic) {
[self setAutomatic: b];
}
return nil;
}
-(void)loadBookmarks {
NSSortDescriptor *s = [NSSortDescriptor sortDescriptorWithKey: @"name" ascending: YES selector: @selector(caseInsensitiveCompare:)];
_items = [NSArrayController new];
[_items setManagedObjectContext: _moc];
[_items setAvoidsEmptySelection: NO];
[_items setAutomaticallyPreparesContent: YES];
[_items setAutomaticallyRearrangesObjects: YES];
[_items setEntityName: @"Bookmark"];
[_items setSortDescriptors: @[ s ]];
[_items fetch: nil];
}
/* extract the number from a trailing " (%d)" */
static int extract_number(NSString *s, NSInteger offset) {
unichar buffer[32];
NSInteger len = [s length] - offset;
unichar c;
int i;
int n = 0;
if (len < 4) return -1; /* " (1)"*/
if (len > 8) return -1; /* " (99999)" */
NSRange r = NSMakeRange(offset, len);
[s getCharacters: buffer range: r];
buffer[len] = 0;
i = 0;
if (buffer[i++] != ' ') return -1;
if (buffer[i++] != '(') return -1;
c = buffer[i++];
if (c < '1' || c > '9') return -1;
n = c - '0';
for (;;) {
c = buffer[i];
if (c < '0' || c > '9') break;
n = n * 10 + (c - '0');
++i;
}
if (buffer[i++] != ')') return -1;
if (buffer[i++] != 0) return -1;
return n;
}
-(NSString *)uniqueBookmarkName: (NSString *)name {
NSInteger length = [name length];
NSError *error = nil;
NSPredicate *p = [NSPredicate predicateWithFormat: @"name BEGINSWITH %@", name];
NSFetchRequest *req = [NSFetchRequest fetchRequestWithEntityName: @"Bookmark"];
[req setPredicate: p];
NSArray *array = [_moc executeFetchRequest: req error: &error];
if (![array count]) return name;
uint64_t bits = 1; /* mark 0 as unavailable */
NSInteger max = 0;
BOOL exact = NO;
for (Bookmark *b in array) {
NSString *s = [b name];
if ([name isEqualToString: s]) {
exact = YES;
continue;
}
int n = extract_number(s, length);
if (n < 1) continue;
if (n > max) max = n;
if (n < 64)
bits |= (1 << n);
}
if (!exact) return name;
if (bits == (uint64_t)-1) {
return [name stringByAppendingFormat: @" (%u)", (int)(max + 1)];
}
#if 1
int ix = 0;
while (bits & 0x01) {
++ix;
bits >>= 1;
}
#else
// this doesn't work correctly.
int ix = __builtin_ffsll(~bits);
#endif
return [name stringByAppendingFormat: @" (%u)", ix];
}
-(BOOL)addDiskImage: (NSObject *)pathOrURL {
NSError *error;
NSString *path = nil;
NSURL *url = nil;
if ([pathOrURL isKindOfClass: [NSString class]]) {
path = (NSString *)pathOrURL;
} else if ([pathOrURL isKindOfClass: [NSURL class]]){
url = (NSURL *)pathOrURL;
path = [NSString stringWithCString: [url fileSystemRepresentation] encoding: NSUTF8StringEncoding];
}
if (!path) return NO;
NSFileManager *fm = [NSFileManager defaultManager];
NSDictionary *attr = [fm attributesOfItemAtPath: path error: &error];
if (error) {
NSLog(@"%@ : %@", path, error);
return NO;
}
NSNumber *size = [attr objectForKey: NSFileSize];
NSDate *now = [NSDate date];
NSPredicate *p = [NSPredicate predicateWithFormat: @"path = %@", path];
NSFetchRequest *req = [NSFetchRequest fetchRequestWithEntityName: @"DiskImage"];
[req setPredicate: p];
NSArray *array = [_moc executeFetchRequest: req error: &error];
BOOL found = 0;
for (NSManagedObject *o in array) {
found = YES;
[o setValue: now forKey: @"accessed"];
}
if (found) return NO;
DiskImage *o = [NSEntityDescription insertNewObjectForEntityForName: @"DiskImage" inManagedObjectContext: _moc];
[o setPath: path];
[o setAdded: now];
[o setAccessed: now];
[o setSize: [size longLongValue]];
[o updatePath];
if (![_moc save: &error]) {
NSLog(@"%@", error);
[_moc deleteObject: o];
}
return YES;
}
-(void)diskImageAdded: (NSNotification *)notification {
NSURL *url = [notification object];
if (url) [self addDiskImage: url];
}
static NSString *kMenuContext = @"";
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if (context == (__bridge void * _Nullable)(kMenuContext)) {
//NSLog(@"observeValueForKeyPath %@", keyPath);
_newMenuGeneration++;
return;
}
[super observeValueForKeyPath: keyPath ofObject: object change: change context: context];
}
-(void)initMenus {
if (!_items) {
[self loadBookmarks];
[_items addObserver: self forKeyPath: @"arrangedObjects.name" options: 0 context: (__bridge void * _Nullable)(kMenuContext)];
[_items addObserver: self forKeyPath: @"arrangedObjects.automatic" options: 0 context: (__bridge void * _Nullable)(kMenuContext)];
}
}
-(IBAction)bookmarkMenu:(id)sender
{
}
-(Bookmark *)currentBookmark {
return _currentBookmark;
}
-(void)setCurrentBookmark:(Bookmark *)currentBookmark {
if (currentBookmark == _currentBookmark) return;
_currentBookmark = currentBookmark;
_newMenuGeneration++;
}
-(void)menuNeedsUpdate:(NSMenu *)menu {
if (_currentMenuGeneration == _newMenuGeneration) return;
_currentMenuGeneration = _newMenuGeneration;
if (_currentBookmark && _updateMenuItem) {
NSString *title = [NSString stringWithFormat: @"Update “%@”", [_currentBookmark name]];
[_updateMenuItem setHidden: NO];
[_updateMenuItem setTitle: title];
[_updateMenuItem setRepresentedObject: _currentBookmark];
} else {
[_updateMenuItem setHidden: YES];
[_updateMenuItem setRepresentedObject: nil];
}
NSArray *menus = [menu itemArray];
for (NSMenuItem *item in [menus reverseObjectEnumerator]) {
if ([item tag] == 0xdeadbeef) [_menu removeItem: item];
}
NSArray *array = [_items arrangedObjects];
for (Bookmark *b in array) {
NSString *title = [b name];
NSMenuItem *item = [menu addItemWithTitle: title action: @selector(bookmarkMenu:) keyEquivalent: @""];
[item setRepresentedObject: b];
[item setTag: 0xdeadbeef];
if ([b automatic]) {
[item setOnStateImage: [NSImage imageNamed: NSImageNameStatusAvailable]];
[item setState: NSOnState];
}
//if ([b automatic]) [item setAttributedTitle: ItalicMenuString([b name])];
//[item setState: [b automatic] ? NSMixedState : NSOffState];
}
}
@end
/* MacOS 12.1+ doesn't like class clusters in nibs -
[General] This coder is expecting the replaced object 0x600000938f60 to be returned from
NSClassSwapper.initWithCoder instead of <BookmarkManager: 0x600000905da0>
*/
@interface BookmarkManagerProxy : NSProxy {
BookmarkManager *_target;
}
@end
@implementation BookmarkManagerProxy
-(id)init {
_target = [BookmarkManager sharedManager];
return self;
}
-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [_target methodSignatureForSelector: sel];
}
+(BOOL)respondsToSelector:(SEL)aSelector {
return [BookmarkManager respondsToSelector: aSelector];
}
-(void)forwardInvocation:(NSInvocation *)invocation {
if ([_target respondsToSelector: [invocation selector]]) {
[invocation invokeWithTarget: _target];
} else {
[super forwardInvocation: invocation];
}
}
@end

View File

@ -0,0 +1,19 @@
//
// BookmarkWindowController.h
// Ample
//
// Created by Kelvin Sherlock on 2/6/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface BookmarkWindowController : NSWindowController
+(instancetype)sharedInstance;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,170 @@
//
// BookmarkWindowController.m
// Ample
//
// Created by Kelvin Sherlock on 2/6/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
#import "BookmarkWindowController.h"
#import "BookmarkManager.h"
#import "Bookmark.h"
#import "Ample.h"
@interface BookmarkWindowController ()
@property (strong) IBOutlet NSArrayController *arrayController;
@property (strong) IBOutlet BookmarkManager *bookmarkManager;
@property (weak) IBOutlet NSTableView *tableView;
@end
@implementation BookmarkWindowController
+(instancetype)sharedInstance {
static BookmarkWindowController *me = nil;
if (!me) {
me = [self new];
}
return me;
}
-(NSString *)windowNibName {
return @"BookmarkWindow";
}
- (void)windowDidLoad {
[super windowDidLoad];
NSSortDescriptor *s = [NSSortDescriptor sortDescriptorWithKey: @"name" ascending: YES selector: @selector(caseInsensitiveCompare:)];
[_arrayController setSortDescriptors: @[s]];
}
-(BOOL)windowShouldClose: (NSWindow *)sender {
NSManagedObjectContext *moc = [_arrayController managedObjectContext];
NSError *error;
if (![_arrayController commitEditing]) return NO;
if ([moc save: &error]) return YES;
NSLog(@"%@", error);
#if 0
NSDictionary *dict = [error userInfo];
NSArray *array = [dict objectForKey: @"conflictList"];
for (NSConstraintConflict *c in array) {
NSArray * arr = [c conflictingObjects];
for (NSManagedObject *o in arr) {
}
}
#endif
return YES;
//[self presentError: error];
//return NO;
}
-(void)keyDown:(NSEvent *)event {
/* Carbon/Events.h */
enum {
kVK_Delete = 0x33,
kVK_ForwardDelete = 0x75,
};
unsigned short keyCode = [event keyCode];
if (keyCode == kVK_Delete || keyCode == kVK_ForwardDelete) {
// arraycontroller selected object / selected index doesn't work right.
NSInteger row = [_tableView selectedRow];
if (row >= 0)
[_arrayController removeObjectAtArrangedObjectIndex: row];
}
}
-(Bookmark *)clickedItem {
NSArray *array = [_arrayController arrangedObjects];
NSInteger row = [_tableView clickedRow];
if (row < 0 || row >= [array count]) return nil;
return [array objectAtIndex: row];
}
-(IBAction)doubleClick:(id)sender {
Bookmark *b = [self clickedItem];
if (!b) return;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName: kNotificationBookmarkMagicRoute object: b];
}
-(IBAction)toggleDefault:(id)sender {
NSLog(@"%@", sender);
}
-(IBAction)setDefault:(id)sender {
Bookmark *b = [self clickedItem];
if (!b) return;
[_bookmarkManager setAutomatic: b];
}
-(IBAction)clearDefault:(id)sender {
Bookmark *b = [self clickedItem];
if (!b) return;
[b setAutomatic: NO];
}
-(IBAction)deleteBookmark:(id)sender {
//Bookmark *b = [self clickedItem];
//if (!b) return;
NSInteger row = [_tableView clickedRow];
if (row >= 0)
[_arrayController removeObjectAtArrangedObjectIndex: row];
}
@end
@implementation BookmarkWindowController (Menu)
-(BOOL)validateMenuItem:(NSMenuItem *)menuItem {
Bookmark *b = [self clickedItem];
if (!b) return NO;
SEL action = [menuItem action];
if (action == @selector(clearDefault:)) {
return [b automatic];
}
if (action == @selector(setDefault:)) {
return ![b automatic];
}
return YES;
}
@end

View File

@ -0,0 +1,17 @@
//
// CheatSheetWindowController.h
// Ample
//
// Created by Kelvin Sherlock on 1/14/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface CheatSheetWindowController : NSWindowController
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,61 @@
//
// CheatSheetWindowController.m
// Ample
//
// Created by Kelvin Sherlock on 1/14/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import "CheatSheetWindowController.h"
#import <WebKit/WebKit.h>
@interface CheatSheetWindowController ()
@property (weak) IBOutlet WKWebView *webView;
@end
@interface CheatSheetWindowController (NavigationDelegate) <WKNavigationDelegate>
@end
@implementation CheatSheetWindowController
-(NSString *)windowNibName {
return @"CheatSheet";
}
- (void)windowDidLoad {
[super windowDidLoad];
if (!_webView) {
WKWebView *webView;
NSWindow *window = [self window];
CGRect frame = [[window contentView] frame];
webView = [WKWebView new];
[webView setFrame: frame];
[webView setNavigationDelegate: self];
[[window contentView]addSubview: webView];
_webView = webView;
}
[_webView setHidden: YES];
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource: @"CheatSheet" withExtension: @"html"];
//[[[_webView configuration] preferences] setValue: @YES forKey: @"developerExtrasEnabled"];
[_webView loadFileURL: url allowingReadAccessToURL: url];
}
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
// delay to prevent flash in dark mode.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0/8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[webView setHidden: NO];
});
}
@end

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="15702" systemVersion="18G9323" minimumToolsVersion="Automatic" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="0">
<entity name="Bookmark" representedClassName="Bookmark" syncable="YES">
<attribute name="automatic" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="comment" optional="YES" attributeType="String"/>
<attribute name="created" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="data" attributeType="Binary"/>
<attribute name="machine" optional="YES" attributeType="String"/>
<attribute name="modified" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="name" attributeType="String" minValueString="1" maxValueString="32"/>
<fetchIndex name="Bookmark_name">
<fetchIndexElement property="name" type="Binary" order="ascending"/>
</fetchIndex>
</entity>
<entity name="DiskImage" representedClassName="DiskImage" syncable="YES">
<attribute name="accessed" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="added" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="name" optional="YES" transient="YES" attributeType="String"/>
<attribute name="path" attributeType="String"/>
<attribute name="size" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<fetchIndex name="DiskImage_path">
<fetchIndexElement property="path" type="Binary" order="ascending"/>
</fetchIndex>
</entity>
<elements>
<element name="Bookmark" positionX="994.5546875" positionY="-404.046875" width="128" height="148"/>
<element name="DiskImage" positionX="1242" positionY="-333" width="128" height="118"/>
</elements>
</model>

View File

@ -0,0 +1,25 @@
//
// Bookmark+CoreDataClass.h
// Ample
//
// Created by Kelvin Sherlock on 2/6/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
NS_ASSUME_NONNULL_BEGIN
@interface Bookmark : NSManagedObject
@property NSDictionary *dictionary;
+(NSString *)uniqueName: (NSString *)name inContext: (NSManagedObjectContext *)context;
@end
NS_ASSUME_NONNULL_END
#import "Bookmark+CoreDataProperties.h"

View File

@ -0,0 +1,175 @@
//
// Bookmark+CoreDataClass.m
// Ample
//
// Created by Kelvin Sherlock on 2/6/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
//
#import "Bookmark+CoreDataClass.h"
@implementation Bookmark
/* extract the number from a trailing " (%d)" */
static int extract_number(NSString *s, NSInteger offset) {
unichar buffer[32];
NSInteger len = [s length] - offset;
unichar c;
int i;
int n = 0;
if (len < 4) return -1; /* " (1)"*/
if (len > 6) return -1; /* " (999)" */
NSRange r = NSMakeRange(offset, len);
[s getCharacters: buffer range: r];
buffer[len] = 0;
i = 0;
if (buffer[i++] != ' ') return -1;
if (buffer[i++] != '(') return -1;
c = buffer[i++];
if (c < '1' || c > '9') return -1;
n = c - '0';
for (;;) {
c = buffer[i];
if (c < '0' || c > '9') break;
n = n * 10 + (c - '0');
++i;
}
if (buffer[i++] != ')') return -1;
if (buffer[i++] != 0) return -1;
return n;
}
+(NSString *)uniqueName: (NSString *)name inContext: (NSManagedObjectContext *)context {
NSInteger length = [name length];
NSError *error = nil;
NSPredicate *p = [NSPredicate predicateWithFormat: @"name BEGINSWITH %@", name];
NSFetchRequest *req = [NSFetchRequest fetchRequestWithEntityName: @"Bookmark"];
[req setPredicate: p];
NSArray *array = [context executeFetchRequest: req error: &error];
if (![array count]) return name;
uint64_t bits = 1; /* mark 0 as unavailable */
NSInteger max = 0;
BOOL exact = NO;
for (Bookmark *b in array) {
NSString *s = [b name];
if ([name isEqualToString: s]) {
exact = YES;
continue;
}
int n = extract_number(s, length);
if (n < 1) continue;
if (n > max) max = n;
if (n < 64)
bits |= (1 << n);
}
if (!exact) return name;
if (bits == (uint64_t)-1) {
if (max == 999) return nil;
return [name stringByAppendingFormat: @" (%u)", (int)(max + 1)];
}
#if 1
int ix = 0;
while (bits) {
++ix;
bits >>= 1;
}
#else
// this doesn't work correctly.
int ix = __builtin_ffsll(~bits);
#endif
return [name stringByAppendingFormat: @" (%u)", ix];
}
-(void)setDictionary:(NSDictionary *)dictionary {
NSData *data;
NSError *error = nil;
data = [NSPropertyListSerialization dataWithPropertyList: dictionary
format: NSPropertyListBinaryFormat_v1_0
options: 0
error: &error];
[self setData: data];
}
-(NSDictionary *)dictionary {
// NSDictionary *dict;
NSData *data = [self data];
NSError *error = nil;
return [NSPropertyListSerialization propertyListWithData: data
options: 0
format: nil
error: &error];
}
- (NSError *)errorFromOriginalError:(NSError *)originalError error:(NSError*)secondError
{
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
NSMutableArray *errors = [NSMutableArray arrayWithObject:secondError];
if ([originalError code] == NSValidationMultipleErrorsError) {
[userInfo addEntriesFromDictionary:[originalError userInfo]];
[errors addObjectsFromArray:[userInfo objectForKey:NSDetailedErrorsKey]];
} else {
[errors addObject:originalError];
}
[userInfo setObject:errors forKey:NSDetailedErrorsKey];
return [NSError errorWithDomain:NSCocoaErrorDomain code:NSValidationMultipleErrorsError userInfo:userInfo];
}
- (BOOL)validateName:(id*)ioValue error:(NSError**)outError {
if (!ioValue || !*ioValue) return YES;
NSString *name = *ioValue;
NSFetchRequest *frq = [NSFetchRequest fetchRequestWithEntityName: @"Bookmark"];
NSPredicate *p = [NSPredicate predicateWithFormat: @"name = %@", name];
[frq setPredicate: p];
NSArray * arr = [[self managedObjectContext] executeFetchRequest: frq error: nil];
BOOL dupe = NO;
for (Bookmark *b in arr) {
if (b == self) continue;
dupe = YES;
break;
}
if (dupe && outError) {
NSDictionary *dict = @{ NSLocalizedFailureReasonErrorKey: @"duplicate name",
NSLocalizedDescriptionKey: @"duplicate name",
NSValidationKeyErrorKey: @"name",
NSValidationValueErrorKey: name,
NSValidationObjectErrorKey: self
};
NSError *e = [NSError errorWithDomain: @"Ample" code: 1 userInfo: dict];
if (*outError) {
*outError = [self errorFromOriginalError: *outError error: e];
} else {
*outError = e;
}
}
return !dupe;
}
@end

View File

@ -0,0 +1,28 @@
//
// Bookmark+CoreDataProperties.h
// Ample
//
// Created by Kelvin Sherlock on 2/6/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
//
#import "Bookmark+CoreDataClass.h"
NS_ASSUME_NONNULL_BEGIN
@interface Bookmark (CoreDataProperties)
+ (NSFetchRequest<Bookmark *> *)fetchRequest;
@property (nullable, nonatomic, copy) NSString *name;
@property (nullable, nonatomic, copy) NSString *machine;
@property (nullable, nonatomic, retain) NSData *data;
@property (nullable, nonatomic, copy) NSDate *created;
@property (nullable, nonatomic, copy) NSDate *modified;
@property (nullable, nonatomic, copy) NSString *comment;
@property (nonatomic) BOOL automatic;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,26 @@
//
// Bookmark+CoreDataProperties.m
// Ample
//
// Created by Kelvin Sherlock on 2/6/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
//
#import "Bookmark+CoreDataProperties.h"
@implementation Bookmark (CoreDataProperties)
+ (NSFetchRequest<Bookmark *> *)fetchRequest {
return [NSFetchRequest fetchRequestWithEntityName:@"Bookmark"];
}
@dynamic name;
@dynamic machine;
@dynamic data;
@dynamic created;
@dynamic modified;
@dynamic comment;
@dynamic automatic;
@end

View File

@ -0,0 +1,21 @@
//
// DiskImage+CoreDataClass.h
// Ample
//
// Created by Kelvin Sherlock on 2/7/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
NS_ASSUME_NONNULL_BEGIN
@interface DiskImage : NSManagedObject
@end
NS_ASSUME_NONNULL_END
#import "DiskImage+CoreDataProperties.h"

View File

@ -0,0 +1,14 @@
//
// DiskImage+CoreDataClass.m
// Ample
//
// Created by Kelvin Sherlock on 2/7/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
//
#import "DiskImage+CoreDataClass.h"
@implementation DiskImage
@end

View File

@ -0,0 +1,29 @@
//
// DiskImage+CoreDataProperties.h
// Ample
//
// Created by Kelvin Sherlock on 2/7/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
//
#import "DiskImage+CoreDataClass.h"
NS_ASSUME_NONNULL_BEGIN
@interface DiskImage (CoreDataProperties)
+ (NSFetchRequest<DiskImage *> *)fetchRequest;
@property (nullable, nonatomic, copy) NSString *path;
@property (nullable, nonatomic, copy) NSDate *added;
@property (nonatomic) int64_t size;
@property (nullable, nonatomic, copy) NSDate *accessed;
@property (nullable, nonatomic, copy) NSString *name;
-(void)updatePath;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,52 @@
//
// DiskImage+CoreDataProperties.m
// Ample
//
// Created by Kelvin Sherlock on 2/7/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
//
#import "DiskImage+CoreDataProperties.h"
#if 0
@interface DiskImage () {
NSString *_name;
}
@end
#endif
@implementation DiskImage (CoreDataProperties)
+ (NSFetchRequest<DiskImage *> *)fetchRequest {
return [NSFetchRequest fetchRequestWithEntityName:@"DiskImage"];
}
@dynamic path;
@dynamic added;
@dynamic size;
@dynamic accessed;
@dynamic name;
-(void)updatePath {
NSString *path = [self primitiveValueForKey: @"path"];
[self setName: [path lastPathComponent]];
}
-(void)awakeFromFetch {
[super awakeFromFetch];
[self updatePath];
}
#if 0
-(void)awakeFromInsert {
[super awakeFromInsert];
NSString *path = [self primitiveValueForKey: @"path"];
[self setName: [path lastPathComponent]];
}
#endif
@end

View File

@ -3,12 +3,22 @@
<plist version="1.0">
<dict>
<key>MameComponentsDate</key>
<date>2020-09-02T16:00:00Z</date>
<date>2024-04-25T12:00:00Z</date>
<key>UseCustomMame</key>
<false/>
<key>AutoCloseLogWindow</key>
<true/>
<key>MamePath</key>
<string>/usr/local/bin/mame</string>
<key>MameWorkingDirectory</key>
<string>/usr/local/share/mame/</string>
<key>NSQuitAlwaysKeepsWindows</key>
<true/>
<key>DefaultDownloadURL</key>
<string>https://archive.org/download/mame-merged/mame-merged</string>
<key>UseLogWindow</key>
<true/>
<key>DefaultDownloadExtension</key>
<string>zip</string>
</dict>
</plist>

14
Ample/DiskImage.h Normal file
View File

@ -0,0 +1,14 @@
//
// DiskImage.h
// Ample
//
// Created by Kelvin Sherlock on 2/7/2022.
// Copyright © 2022 Kelvin Sherlock. All rights reserved.
//
#ifndef DiskImage_h
#define DiskImage_h
#import "DiskImage+CoreDataClass.h"
#endif /* DiskImage_h */

View File

@ -0,0 +1,28 @@
//
// DiskImagesWindowController.h
// Ample
//
// Created by Kelvin Sherlock on 9/13/2020.
// Copyright © 2020 Kelvin Sherlock. All rights reserved.
//
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface DiskImagesWindowController : NSWindowController <NSWindowRestoration>
+(instancetype)sharedInstance;
@end
@interface DiskImagesWindowController (TableView) <NSTableViewDelegate, NSTableViewDataSource>
@end
@interface DiskImagesWindowController (Menu) <NSMenuDelegate>
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,349 @@
//
// DiskImagesWindowController.m
// Ample
//
// Created by Kelvin Sherlock on 9/13/2020.
// Copyright © 2020 Kelvin Sherlock. All rights reserved.
//
#import "DiskImagesWindowController.h"
#import "TableCellView.h"
#import "Ample.h"
#import "DiskImage.h"
#import "BookmarkManager.h"
@interface DiskImagesWindowController ()
@property (weak) IBOutlet NSTableView *tableView;
@property (strong) IBOutlet NSArrayController *arrayController;
@end
@implementation DiskImagesWindowController {
NSSet *_extensions;
}
+(instancetype)sharedInstance {
static DiskImagesWindowController *me;
if (!me) {
me = [self new];
}
return me;
}
+ (void)restoreWindowWithIdentifier:(NSUserInterfaceItemIdentifier)identifier state:(NSCoder *)state completionHandler:(void (^)(NSWindow *, NSError *))completionHandler {
NSLog(@"restore disk images window");
NSWindowController *controller = [self sharedInstance];
NSWindow *w = [controller window];
[w restoreStateWithCoder: state];
completionHandler(w, nil);
}
-(instancetype)init {
if ((self = [super init])) {
//[self loadRecentDiskImages];
_extensions = [NSSet setWithObjects:
@"2img", @"2mg", @"chd", @"dc", @"do", @"dsk", @"hd", @"hdv", @"image", @"nib", @"po", @"wav", @"woz", @"iso", @"raw",
// st, etc.
@"mfm", @"st", @"msa", @"stx", @"ipf",
//
@"rom", @"bin",
// not supported/relevant.
// @"mfi", @"dfi", @"hfe", @"d77" @"d88", @"1dd", @"cqm", @"cqi", @"td0", @"imd",
nil
];
}
return self;
}
-(NSString *)windowNibName {
return @"DiskImages";
}
- (void)windowDidLoad {
[super windowDidLoad];
NSWindow *window = [self window];
[window setRestorable: YES];
[window setRestorationClass: [self class]];
if (@available(macOS 10.13, *)) {
[_tableView registerForDraggedTypes: @[NSPasteboardTypeFileURL]];
} else {
[_tableView registerForDraggedTypes: @[ (NSString *)kUTTypeFileURL ]];
}
[_tableView setDraggingSourceOperationMask: NSDragOperationCopy forLocal: NO]; // enable drag/drop to othr apps.
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
NSSortDescriptor *s = [NSSortDescriptor sortDescriptorWithKey: @"name" ascending: YES selector: @selector(caseInsensitiveCompare:)];
[_arrayController setSortDescriptors: @[ s ]];
}
#if 0
-(void)loadRecentDiskImages {
// NSError *error;
NSURL *sd = SupportDirectory();
NSURL *url = [sd URLByAppendingPathComponent: @"RecentDiskImages.plist"];
NSData *data = [NSData dataWithContentsOfURL: url];
if (data) {
_content = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainers format:nil error: nil];
}
if (!_content)
_content = [NSMutableArray new];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver: self selector: @selector(diskImageAdded:) name: kNotificationDiskImageAdded object: nil];
[nc addObserver: self selector: @selector(willTerminate:) name: NSApplicationWillTerminateNotification object: nil];
}
-(void)timerCallback: (NSTimer *)timer {
_timer = nil;
[self saveFile];
}
#endif
-(void)diskImageAdded: (NSNotification *)notification {
NSURL *url = [notification object];
if (!url) return;
//[self addFile: url];
}
#if 0
-(void)markDirty {
_dirty = YES;
if (_timer) [_timer invalidate];
_timer = [NSTimer scheduledTimerWithTimeInterval: 5 * 60 target: self selector: @selector(timerCallback:) userInfo: nil repeats: NO];
#if 0
// 10.12+
_timer = [NSTimer scheduledTimerWithTimeInterval: 5 * 60 repeats: NO block: ^(NSTimer *t) {
self->_timer = nil;
[self saveFile];
}];
#endif
}
-(void)saveFile {
[_timer invalidate];
_timer = nil;
NSURL *sd = SupportDirectory();
NSURL *url = [sd URLByAppendingPathComponent: @"RecentDiskImages.plist"];
if (_content && url) {
[_content writeToURL: url atomically: YES];
}
_dirty = NO;
}
-(void)willTerminate: (NSNotification *)notification {
// if dirty, write data....
if (!_dirty) return;
[self saveFile];
}
#endif
#if 0
-(BOOL)addFile: (NSObject *)pathOrURL {
NSString *path = nil;
NSURL *url = nil;
if ([pathOrURL isKindOfClass: [NSString class]]) {
path = (NSString *)pathOrURL;
} else if ([pathOrURL isKindOfClass: [NSURL class]]){
url = (NSURL *)pathOrURL;
path = [NSString stringWithCString: [url fileSystemRepresentation] encoding: NSUTF8StringEncoding];
}
if (!path) return NO;
// todo -- check if file is in the list already...
BOOL found = NO;
// should really compare the volume id / ino I suppose.
for (NSMutableDictionary *d in _content) {
NSString *s = [d objectForKey: @"path"];
if ([path compare: s] == NSOrderedSame) {
found = YES;
[d setObject: [NSDate new] forKey: @"date"];
[self markDirty];
break;
}
}
if (found) return NO;
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error;
NSDictionary *attr = [fm attributesOfItemAtPath: path error: &error];
if (error) {
NSLog(@"%@ : %@", path, error);
return NO;
}
NSNumber *size = [attr objectForKey: NSFileSize];
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithObjectsAndKeys:
path, @"path",
size, @"size",
[NSDate new], @"date",
nil];
#if 0
@synchronized (self) {
if (_arrayController)
[_arrayController addObject: d];
else
[_content addObject: d];
}
#endif
[self markDirty];
return YES;
}
#endif
-(DiskImage *)clickedItem {
NSArray *array = [_arrayController arrangedObjects];
NSInteger row = [_tableView clickedRow];
if (row < 0 || row >= [array count]) return nil;
return [array objectAtIndex: row];
}
#pragma mark - IBActions
- (IBAction)filter:(id)sender {
NSString *text = [sender stringValue];
NSPredicate *p = nil;
if ([text length]) {
p = [NSPredicate predicateWithFormat: @"name CONTAINS[cd] %@",text];
}
[_arrayController setFilterPredicate: p];
}
- (IBAction)showInFinder:(id)sender {
DiskImage *item = [self clickedItem];
if (!item) return;
NSString *path = [item path];
NSURL *url = [NSURL fileURLWithPath: path];
if (!url) return;
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws activateFileViewerSelectingURLs: @[url]];
}
- (IBAction)eject:(id)sender {
DiskImage *item = [self clickedItem];
if (!item) return;
[_arrayController removeObject: item];
}
-(IBAction)doubleClick: (id)sender {
DiskImage *d = [self clickedItem];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSDictionary *userInfo = @{ @"path": [d path] };
[nc postNotificationName: kNotificationDiskImageMagicRoute object: nil userInfo: userInfo];
}
@end
@implementation DiskImagesWindowController (TableView)
-(id<NSPasteboardWriting>)tableView:(NSTableView *)tableView pasteboardWriterForRow:(NSInteger)row {
id objects = [_arrayController arrangedObjects];
DiskImage *d = [objects objectAtIndex: row];
if (!d) return nil;
NSString *path = [d path];
NSURL *url = [NSURL fileURLWithPath: path];
return url;
#if 0
NSPasteboardItem *item = [NSPasteboardItem new];
[item setString: [url absoluteString] forType: NSPasteboardTypeFileURL]; // FileURL
[item setString: path forType: NSPasteboardTypeString]; // for Terminal.app
return item;
#endif
}
-(NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id<NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation {
if ([info draggingSource] == _tableView) return NSDragOperationNone;
// option key will ignore all filetype restrictions.
if ([NSEvent modifierFlags] & NSEventModifierFlagOption) return NSDragOperationCopy;
// this only checks the first dragged item...
NSPasteboard * pb = [info draggingPasteboard];
NSURL *url = [NSURL URLFromPasteboard: pb];
NSString *ext = [url pathExtension];
ext = [ext lowercaseString];
if ([_extensions containsObject: ext])
return NSDragOperationCopy;
return NSDragOperationNone;
}
-(BOOL)tableView:(NSTableView *)tableView acceptDrop:(id<NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation {
BookmarkManager *bm = [BookmarkManager sharedManager];
if ([info draggingSource] == _tableView) return NO;
NSPasteboard * pb = [info draggingPasteboard];
BOOL ok = NO;
for (NSPasteboardItem *item in [pb pasteboardItems]) {
// need to convert from a string to a url back to a file in case it's a file id url?
NSString *s;
if (@available(macOS 10.13, *)) {
s = [item stringForType: NSPasteboardTypeFileURL];
} else {
// El Capitan still has kUTTypeFileURL aka public.file-url but doesn't have NSPasteboardTypeFileURL
s = [item stringForType: (NSString *)kUTTypeFileURL];
}
if (!s) continue;
NSURL *url = [NSURL URLWithString: s];
if (!url) continue;
ok |= [bm addDiskImage: url];
//ok |= [self addFile: url];
}
return ok;
}
@end

View File

@ -10,7 +10,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface DownloadWindowController : NSWindowController
@interface DownloadWindowController : NSWindowController <NSWindowRestoration>
@property NSString *currentROM;
@property NSInteger currentCount;
@ -18,22 +18,17 @@ NS_ASSUME_NONNULL_BEGIN
@property NSInteger errorCount;
@property BOOL active;
+(instancetype)sharedInstance;
@end
@interface DownloadWindowController (URL) <NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate>
@end
@interface DownloadWindowController (Table) <NSTableViewDelegate, NSTableViewDataSource>
@end
@interface DownloadWindowController (Menu) <NSMenuDelegate, NSMenuItemValidation>
@end
@interface DownloadTableCellView : NSTableCellView
@property (weak) IBOutlet NSTextField *statusTextField;
@property (weak) IBOutlet NSProgressIndicator *activity;
@end
NS_ASSUME_NONNULL_END

View File

@ -8,6 +8,70 @@
#import "Ample.h"
#import "DownloadWindowController.h"
#import "Menu.h"
static NSString *Extensions[] = { @"zip", @"7z" };
enum {
kTagZip = 1,
kTag7z = 2,
};
@interface DownloadExtensionTransformer: NSValueTransformer
@end
@implementation DownloadExtensionTransformer
+(void)load {
[NSValueTransformer setValueTransformer: [DownloadExtensionTransformer new] forName: @"FormatTransformer"];
}
+ (Class)transformedValueClass {
return [NSString class];
}
+ (BOOL)allowsReverseTransformation {
return YES;
}
-(id)transformedValue:(id)value {
// string to number.
if ([@"zip" isEqualToString: value])
return @(kTagZip);
if ([@"7z" isEqualToString: value])
return @(kTag7z);
return @0;
}
-(id)reverseTransformedValue:(id)value {
// number back to string.
switch ([value intValue]) {
case kTagZip: return @"zip";
case kTag7z: return @"7z";
default: return @"";
}
}
+(unsigned)stringToNumber: (NSString *)string {
if ([@"zip" isEqualToString: string])
return kTagZip;
if ([@"7z" isEqualToString: string])
return kTag7z;
return 0;
}
+(NSString *)numberToString: (unsigned)number {
switch (number) {
case kTagZip: return @"zip";
case kTag7z: return @"7z";
default: return @"";
}
}
@end
enum {
ItemMissing = 0,
@ -20,6 +84,7 @@ enum {
@interface DownloadItem : NSObject
@property NSString *value;
@property NSString *name;
@property NSError *error;
@property NSString *pathName;
@ -28,136 +93,243 @@ enum {
@property NSUInteger status;
@property NSUInteger index;
@property NSUInteger fileSize;
@property (readonly) NSColor *titleColor;
@property (readonly) NSColor *descriptionColor;
-(void)cancelDownload;
-(void)beginDownloadWithTask:(NSURLSessionDownloadTask *)task;
-(void)completeWithError: (NSError *)error;
-(NSString *)statusDescription;
-(void)refresh: (NSURL *)localURL;
@end
@interface DownloadItemArrayController : NSArrayController
@property(readonly, copy) NSArray<NSString *> *automaticRearrangementKeyPaths;
@end
@implementation DownloadItemArrayController
-(NSArray<NSString *> *)automaticRearrangementKeyPaths {
return @[@"localURL"]; // , @"error", @"task", @"statusDescription"];
}
@end
@interface DownloadWindowController ()
@property (weak) IBOutlet NSTableView *tableView;
@property (weak) IBOutlet NSPopUpButton *formatButton;
@property (weak) IBOutlet NSTextField *downloadField;
@property NSString *downloadExtension;
/* filter buttons */
@property (weak) IBOutlet NSButton *allFilterButton;
@property (weak) IBOutlet NSButton *missingFilterButton;
@property (strong) IBOutlet NSArrayController *arrayController;
@end
@implementation DownloadWindowController {
NSArray *_items;
NSURL *_romFolder;
NSURL *_sourceURL;
NSURL *_defaultDownloadURL;
NSURL *_downloadURL;
NSURLSession *_session;
NSMutableDictionary *_taskIndex;
NSUserDefaults *_defaults;
NSArray<NSButton *> *_filterButtons;
}
+(instancetype)sharedInstance {
static DownloadWindowController *me = nil;
if (!me) {
me = [self new];
}
return me;
}
+ (void)restoreWindowWithIdentifier:(nonnull NSUserInterfaceItemIdentifier)identifier state:(nonnull NSCoder *)state completionHandler:(nonnull void (^)(NSWindow * _Nullable, NSError * _Nullable))completionHandler {
NSLog(@"restore rom manager window");
NSWindowController *controller = [DownloadWindowController sharedInstance];
NSWindow *w = [controller window];
[w restoreStateWithCoder: state];
completionHandler(w, nil);
}
#if 0
- (void)encodeWithCoder:(nonnull NSCoder *)coder {
}
#endif
-(NSString *)windowNibName {
return @"DownloadWindow";
}
-(void)windowWillLoad {
_defaults = [NSUserDefaults standardUserDefaults];
// set here so binding works.
NSString *s = [_defaults stringForKey: kDownloadExtension];
if (![s length]) s = [_defaults stringForKey: kDefaultDownloadExtension];
_downloadExtension = s;
}
- (void)windowDidLoad {
[super windowDidLoad];
#if 0
NSWindow *window = [self window];
// disabled for now ... restoration happens before defaults are loaded.
[window setRestorable: YES];
[window setRestorationClass: [self class]];
#endif
_filterButtons = @[
_allFilterButton,
_missingFilterButton
];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
NSError *error = nil;
NSBundle *bundle = [NSBundle mainBundle];
NSFileManager *fm = [NSFileManager defaultManager];
#ifdef AMPLE_LITE
NSURL *url = [bundle URLForResource: @"roms~extra" withExtension: @"plist"];
#else
NSURL *url = [bundle URLForResource: @"roms" withExtension: @"plist"];
NSDictionary *d = [NSDictionary dictionaryWithContentsOfURL: url];
#endif
NSArray *roms = [NSArray arrayWithContentsOfURL: url];
NSURL *sd = SupportDirectory();
NSString *romdir = [SupportDirectoryPath() stringByAppendingPathComponent: @"roms"];
_romFolder = [sd URLByAppendingPathComponent: @"roms"];
[fm createDirectoryAtURL: _romFolder withIntermediateDirectories: YES attributes: nil error: &error];
// so blank URL isn't overwritten.
NSString *s = [_defaults stringForKey: kDefaultDownloadURL];
_defaultDownloadURL = [NSURL URLWithString: s];
[_downloadField setPlaceholderString: s];
s = [_defaults stringForKey: kDownloadURL];
if ([s length]) {
[_downloadField setStringValue: s];
_downloadURL = [NSURL URLWithString: s];
} else {
_downloadURL = _defaultDownloadURL;
}
[self initializeExtensionMenu];
NSArray *roms = [d objectForKey: @"roms"];
[self setCurrentROM: @""];
[self setCurrentCount: 0];
[self setTotalCount: [roms count]];
[self setErrorCount: 0];
_sourceURL = [NSURL URLWithString: @"https://archive.org/download/mame0224_rom"]; // hardcoded....
NSMutableArray *tmp = [NSMutableArray arrayWithCapacity: [roms count]];
unsigned ix = 0;
for (NSString *name in roms) {
for (NSDictionary *d in roms) {
DownloadItem *item = [DownloadItem new];
[item setName: name];
[item setValue: [d objectForKey: @"value"]];
[item setName: [d objectForKey: @"description"]];
[item setIndex: ix++];
[tmp addObject: item];
// check if the file exists.
NSString *s = [romdir stringByAppendingPathComponent: name];
NSString *path;
path = [s stringByAppendingPathExtension: @"zip"];
if ([fm fileExistsAtPath: path]) {
[item setStatus: ItemFound];
[item setLocalURL: [NSURL fileURLWithPath: path]];
continue;
}
path = [s stringByAppendingPathExtension: @"7z"];
if ([fm fileExistsAtPath: path]) {
[item setStatus: ItemFound];
[item setLocalURL: [NSURL fileURLWithPath: path]];
continue;
}
}
_items = tmp;
[self refreshROMs: nil];
[_arrayController setContent: _items];
//[_tableView reloadData];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration: config delegate: self delegateQueue: nil];
_taskIndex = [NSMutableDictionary dictionaryWithCapacity: [_items count]];
//[self download];
}
#if 0
-(void)validateURL: (NSString *)url {
NSURL *v;
if (![url length]) {
_effectiveURL = [NSURL URLWithString: _downloadURL];
[_downloadField setTextColor: nil];
return;
}
v = [NSURL URLWithString: url];
if (v) {
_effectiveURL = v;
[_downloadField setTextColor: nil];
} else {
_effectiveURL = [NSURL URLWithString: _downloadURL];
[_downloadField setTextColor: [NSColor systemRedColor]];
}
}
#endif
-(void)downloadItem: (DownloadItem *)item {
if (!_session) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration: config delegate: self delegateQueue: nil];
}
NSURLSessionDownloadTask *task;
NSString *s = [item name];
NSString *path = [s stringByAppendingString: @".7z"]; // hardcoded.
NSURL *url = [_sourceURL URLByAppendingPathComponent: path];
NSString *s = [item value];
NSString *path = [s stringByAppendingPathExtension: _downloadExtension];
NSURL *url = [_downloadURL URLByAppendingPathComponent: path];
task = [_session downloadTaskWithURL: url];
[item beginDownloadWithTask: task];
[_taskIndex setObject: item forKey: task];
[task resume];
}
-(void)download {
// run in thread?
//unsigned count = 0;
for (DownloadItem *item in _items) {
NSURLSessionDownloadTask *task;
NSString *s = [item name];
NSString *path = [s stringByAppendingString: @".7z"]; // hardcoded.
NSURL *url = [_sourceURL URLByAppendingPathComponent: path];
NSString *s = [item value];
NSString *path = [s stringByAppendingPathExtension: _downloadExtension];
NSURL *url = [_downloadURL URLByAppendingPathComponent: path];
task = [_session downloadTaskWithURL: url];
[_taskIndex setObject: item forKey: task];
[item setTask: task];
[task resume];
@ -166,24 +338,55 @@ enum {
//if (count >= 2) break;
}
[self setActive: YES];
}
-(DownloadItem *)clickedItem {
NSInteger row = [_tableView clickedRow];
if (row < 0 || row >= [_items count]) return nil;
return [_items objectAtIndex: row];
return [[_arrayController arrangedObjects] objectAtIndex: row];
//return [_items objectAtIndex: row];
}
#if 0
-(void)redrawRow: (NSUInteger)row {
//NSRect r = [_tableView rectOfRow: row];
//[_tableView setNeedsDisplayInRect: r];
NSIndexSet *rIx = [NSIndexSet indexSetWithIndex: row];
NSIndexSet *cIx = [NSIndexSet indexSetWithIndex: 0];
[_tableView reloadDataForRowIndexes: rIx columnIndexes: cIx];
}
#endif
-(void)initializeExtensionMenu {
unsigned tag;
// mark default download extension.
NSString *defaultExt = [_defaults stringForKey: kDefaultDownloadExtension];
tag = [DownloadExtensionTransformer stringToNumber: defaultExt];
NSMenuItem *item = [[_formatButton menu] itemWithTag: tag];
if (item) {
[item setAttributedTitle: ItalicMenuString([item title])];
}
#if 0
// handled via binding.
NSString *ext = [_defaults stringForKey: kDownloadExtension];
if ([ext length]) {
ix = [DownloadExtensionTransformer stringToNumber: ext];
}
[_formatButton selectItemWithTag: tag];
#endif
}
-(void) defocus {
[[self window] makeFirstResponder: nil];
}
#pragma mark - IBActions
-(IBAction)cancelAll:(id)sender {
@ -197,13 +400,11 @@ enum {
[_taskIndex removeAllObjects];
[self setCurrentCount: 0];
[self setActive: NO];
[_tableView reloadData];
//[_tableView setNeedsDisplay: YES]; // doesn't work...
}
- (IBAction)downloadMissing:(id)sender {
[self defocus];
BOOL delta = NO;
for (DownloadItem *item in _items) {
NSURL *url = [item localURL];
@ -213,10 +414,43 @@ enum {
delta = YES;
}
}
if (delta) {
[self setActive: YES];
[_tableView reloadData];
}
}
- (IBAction)showRomFolder:(id)sender {
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws openURL: _romFolder];
}
-(IBAction)refreshROMs: (id)sender {
NSString *romdir = [SupportDirectoryPath() stringByAppendingPathComponent: @"roms"];
NSFileManager *fm = [NSFileManager defaultManager];
for (DownloadItem *item in _items) {
NSDictionary *attr = nil;
NSString *value = [item value];
NSString *s = [romdir stringByAppendingPathComponent: value];
NSString *path;
for (unsigned i = 0; i < 2; ++i) {
path = [s stringByAppendingPathExtension: Extensions[i]];
attr = [fm attributesOfItemAtPath: path error: nil];
if (attr) break;
}
if (attr) {
[item setStatus: ItemFound];
[item setLocalURL: [NSURL fileURLWithPath: path]];
[item setFileSize: [attr fileSize]];
} else {
[item setStatus: ItemMissing];
[item setLocalURL: nil];
[item setFileSize: 0];
}
}
}
@ -230,37 +464,125 @@ enum {
[ws activateFileViewerSelectingURLs: @[url]];
}
- (IBAction)moveToTrash:(id)sender {
NSError *error = nil;
DownloadItem *item = [self clickedItem];
if (!item) return;
NSURL *url = [item localURL];
if (!url) return;
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm trashItemAtURL: url resultingItemURL: NULL error: &error]) {
[item refresh: nil];
} else {
[self presentError: error];
}
}
-(IBAction)doubleClick:(id)sender {
[self download: sender];
}
- (IBAction)download:(id)sender {
DownloadItem *item = [self clickedItem];
if (!item) return;
[self defocus];
[self downloadItem: item];
[self setActive: YES];
[self redrawRow: [item index]];
}
- (IBAction)cancel:(id)sender {
DownloadItem *item = [self clickedItem];
if (!item) return;
[item cancelDownload];
[self redrawRow: [item index]];
}
// binding screws up with placeholder.
-(IBAction)downloadURLChanged: (NSTextField *)sender {
NSString *value;
value = [sender stringValue];
if (![value length]) {
[_defaults removeObjectForKey: kDownloadURL];
_downloadURL = _defaultDownloadURL;
return;
}
// [self validateURL: value];
[_defaults setValue: value forKey: kDownloadURL];
_downloadURL = [NSURL URLWithString: value];
}
- (IBAction)downloadExtensionChanged:(id)sender {
[_defaults setValue: _downloadExtension forKey: kDownloadExtension];
}
- (IBAction)filterButton:(id)sender {
NSPredicate *p = nil;
NSUInteger tag = [sender tag];
[sender setState: NSControlStateValueOn];
for (NSButton *b in _filterButtons) {
if (b != sender) [b setState: NSControlStateValueOff];
}
switch (tag) {
case 1: // all
default:
[_arrayController setFilterPredicate: nil];
break;
case 2: // missing.
p = [NSPredicate predicateWithBlock: ^BOOL(DownloadItem *item, NSDictionary *bindings){
NSURL *localURL = [item localURL];
return localURL == nil;
}];
[_arrayController setFilterPredicate: p];
break;
}
}
#pragma mark - NSURLSessionDelegate
static NSInteger TaskStatusCode(NSURLSessionTask *task) {
NSURLResponse *response = [task response];
if ([response isKindOfClass: [NSHTTPURLResponse class]]) {
return [(NSHTTPURLResponse *)response statusCode];
}
return -1;
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
if (error) NSLog(@"Download error: %@", error);
NSInteger statusCode = TaskStatusCode(task);
if (!error && statusCode != 200) {
// treat as an error.
NSDictionary *info = @{
NSURLErrorKey: [[task originalRequest] URL],
NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode: statusCode],
};
error = [NSError errorWithDomain: NSURLErrorDomain code: NSURLErrorFileDoesNotExist userInfo: info];
}
// not sure if strictly necessary but this happens in a background thread
// and these are used in KVO binding. Also, main thread only
// means no race conditions.
dispatch_async(dispatch_get_main_queue(), ^(void){
if (error)
if (error) {
[self setErrorCount: self->_errorCount + 1];
else
} else {
[self setCurrentCount: self->_currentCount + 1];
}
NSMutableDictionary *taskIndex = self->_taskIndex;
DownloadItem *item = [taskIndex objectForKey: task];
[taskIndex removeObjectForKey: task];
@ -268,119 +590,187 @@ enum {
if ([taskIndex count] == 0) {
[self setActive: NO];
}
if (item) {
[item completeWithError: error];
NSUInteger row = [item index];
[self redrawRow: row];
}
});
}
- (void)URLSession:(NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)task didFinishDownloadingToURL:(nonnull NSURL *)location {
// NSLog(@"%@", task);
// NSLog(@"%@", [task response]);
if (TaskStatusCode(task) != 200) return;
// need to move to the destination directory...
// file deleted after this function returns, so can't move asynchronously.
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *src = [[task originalRequest] URL];
NSURL *dest = [_romFolder URLByAppendingPathComponent: [src lastPathComponent]];
NSError *error = nil;
/* just in case ... */
[fm removeItemAtURL: dest error: NULL];
[fm moveItemAtURL: location toURL: dest error: &error];
DownloadItem *item = [_taskIndex objectForKey: task];
[item setLocalURL: dest];
/*
dispatch_async(dispatch_get_main_queue(), ^(void){
NSMutableDictionary *taskIndex = self->_taskIndex;
DownloadItem *item = [taskIndex objectForKey: task];
if (error) [item completeWithError: error];
else [item refresh: dest];
});
[item setLocalURL: dest];
}
*/
NSLog(@"%@", src);
}
@end
@implementation DownloadWindowController (Table)
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [_items count];
-(NSURLCredential *)credentialForChallenge: (NSURLAuthenticationChallenge *)challenge {
//if ([challenge previousFailureCount]) return nil;
NSURLCredential *credential = nil;
NSURLProtectionSpace *space = [challenge protectionSpace];
OSStatus status;
NSDictionary *query;
CFTypeRef item = nil;
query = @{
(id)kSecClass: (id)kSecClassInternetPassword,
(id)kSecReturnData: (id)kCFBooleanTrue,
(id)kSecReturnAttributes: (id)kCFBooleanTrue,
(id)kSecAttrServer: [space host],
//(id)kSecAttrProtocol: [space protocol],
(id)kSecMatchLimit: (id)kSecMatchLimitOne,
};
status = SecItemCopyMatching((CFDictionaryRef)query, &item);
//NSLog(@"%@", query);
if (status != 0) return nil;
NSDictionary *d = (__bridge NSDictionary *)item;
//NSLog(@"%@", d);
NSString *account = [d objectForKey: (id)kSecAttrAccount];
NSData *passwordData = [d objectForKey: (id)kSecValueData];
NSString *password = [[NSString alloc] initWithData: passwordData encoding: NSUTF8StringEncoding];
credential = [NSURLCredential credentialWithUser: account password: password persistence: NSURLCredentialPersistenceForSession];
return credential;
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return [_items objectAtIndex: row];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
NSLog(@"challenge: %@", challenge);
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
DownloadItem *item = [_items objectAtIndex: row];
DownloadTableCellView *v = [tableView makeViewWithIdentifier: @"DownloadCell" owner: self];
[[v textField] setObjectValue: [item name]];
NSTextField *tf = [v statusTextField];
[tf setObjectValue: [item statusDescription]];
if ([item error]) {
[tf setTextColor: [NSColor redColor]];
} else {
[tf setTextColor: [NSColor blackColor]];
//if ([tableView isRowSelected: row]){
//[tf setTextColor: [NSColor whiteColor]];
//}
if ([challenge previousFailureCount]) {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
return;
}
if ([item task]) {
[[v activity] startAnimation: nil];
} else {
[[v activity] stopAnimation: nil];
NSURLProtectionSpace *space = [challenge protectionSpace];
NSString *method = [space authenticationMethod];
if ([NSURLAuthenticationMethodHTTPBasic isEqualToString: method] ||
[NSURLAuthenticationMethodNTLM isEqualToString: method] ||
[NSURLAuthenticationMethodHTTPDigest isEqualToString: method]) {
NSURLCredential *credential = [self credentialForChallenge: challenge];
if (credential) {
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
return;
}
}
return v;
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
@end
@implementation DownloadTableCellView
@end
@implementation DownloadItem
-(void)beginDownloadWithTask:(NSURLSessionDownloadTask *)task {
_task = task;
_error = nil;
if (task) _status = ItemDownloading;
[self setTask: task];
[self setError: nil];
if (task) [self setStatus: ItemDownloading];
}
-(void)cancelDownload {
if (!_task) return;
[_task cancel];
_task = nil;
_status = ItemCanceled;
[self setTask: nil];
[self setStatus: ItemCanceled];
}
-(void)completeWithError: (NSError *)error {
_task = nil;
[self setTask: nil];
if (error) {
_error = error;
_status = ItemError;
[self setError: error];
[self setStatus: ItemError];
} else {
// what if there was an error moving it?
_error = nil;
_status = ItemDownloaded;
[self setError: nil];
[self setStatus: ItemDownloaded];
}
}
-(void)refresh: (NSURL *)localURL {
NSDictionary *attr = nil;
NSError * error = nil;
NSFileManager *fm = [NSFileManager defaultManager];
if (localURL) {
attr = [fm attributesOfItemAtPath: [localURL path] error: &error];
} else {
NSString *romdir = [SupportDirectoryPath() stringByAppendingPathComponent: @"roms"];
NSString *s = [romdir stringByAppendingPathComponent: _value];
NSString *path = nil;
for (unsigned i = 0; i < 2; ++i) {
path = [s stringByAppendingPathExtension: Extensions[i]];
attr = [fm attributesOfItemAtPath: path error: nil];
if (attr) {
localURL = [NSURL fileURLWithPath: path];
break;
}
}
}
if (attr && localURL) {
[self setLocalURL: localURL];
[self setFileSize: [attr fileSize]];
[self setStatus: ItemFound];
} else {
[self setLocalURL: nil];
[self setFileSize: 0];
if (_status == ItemFound || _status == ItemDownloaded)
[self setStatus: ItemMissing];
}
}
+(NSSet *)keyPathsForValuesAffectingStatusDescription {
return [NSSet setWithObjects: @"error", @"status", nil];
}
-(NSString *)statusDescription {
static NSString *Names[] = {
@ -391,12 +781,25 @@ enum {
@"Canceled",
@"Error"
};
if (_error) return [_error description];
if (_error) return [_error localizedDescription];
if (_status > sizeof(Names)/sizeof(Names[0])) return @"Unknown";
return Names[_status];
}
+(NSSet *)keyPathsForValuesAffectingTitleColor {
return [NSSet setWithObject: @"localURL"];
}
-(NSColor *)titleColor {
return _localURL ? nil : [NSColor systemRedColor];
}
+(NSSet *)keyPathsForValuesAffectingDescriptionColor {
return [NSSet setWithObject: @"error"];
}
-(NSColor *)descriptionColor {
return _error ? [NSColor systemRedColor] : nil;
}
@end
@ -410,24 +813,34 @@ enum {
};
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
SEL action = [menuItem action];
if (action == @selector(downloadExtensionChanged:)) return YES;
DownloadItem *item = [self clickedItem];
if (!item) return NO;
#if 0
NSInteger row = [_tableView clickedRow];
if (row < 0) return NO;
DownloadItem *item = [_items objectAtIndex: row];
DownloadItem *item = [[_arrayController arrangedObjects] objectAtIndex: row]; //[_items objectAtIndex: row];
#endif
NSUInteger status = [item status];
switch([menuItem tag]) {
case kOpenInFinder:
return status == ItemFound || status == ItemDownloaded;
break;
case kDownload:
return YES;
//return status == ItemMissing || status == ItemError || status == ItemCanceled;
break;
case kCancel:
return status == ItemDownloading;
break;
if (action == @selector(moveToTrash:)) {
return [item localURL] != nil;
}
if (action == @selector(showInFinder:)) {
return [item localURL] != nil;
}
if (action == @selector(download:)) {
return YES;
}
if (action == @selector(cancel:)) {
return status == ItemDownloading;
}
return NO;
}

17
Ample/EjectButton.h Normal file
View File

@ -0,0 +1,17 @@
//
// EjectButton.h
// Ample
//
// Created by Kelvin Sherlock on 9/7/2020.
// Copyright © 2020 Kelvin Sherlock. All rights reserved.
//
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface EjectButton : NSButton
@end
NS_ASSUME_NONNULL_END

60
Ample/EjectButton.m Normal file
View File

@ -0,0 +1,60 @@
//
// EjectButton.m
// Ample
//
// Created by Kelvin Sherlock on 9/7/2020.
// Copyright © 2020 Kelvin Sherlock. All rights reserved.
//
#import "EjectButton.h"
static NSImage *ejectImage = nil;
static NSImage *ejectHoverImage = nil;
@implementation EjectButton {
NSTrackingRectTag _tracking;
BOOL _mouse;
}
+(void)initialize {
// content tint only works with template images.
ejectImage = [NSImage imageNamed: @"eject-16x16"];
ejectHoverImage = [NSImage imageNamed: @"eject-hover-16x16"];
[ejectImage setTemplate: YES];
[ejectHoverImage setTemplate: YES];
}
-(void)awakeFromNib {
[super awakeFromNib];
[self setButtonType: NSButtonTypeMomentaryPushIn];
[self setImage: ejectImage];
[self setAlternateImage: ejectHoverImage];
// _tracking = [self addTrackingRect: [self bounds] owner: self userData: nil assumeInside: NO];
}
-(void)viewDidMoveToWindow {
if (!_tracking)
_tracking = [self addTrackingRect: [self bounds] owner: self userData: nil assumeInside: NO];
}
-(void)mouseEntered:(NSEvent *)event {
_mouse = YES;
if ([self isEnabled])
[self setImage: ejectHoverImage];
}
-(void)mouseExited:(NSEvent *)event {
_mouse = NO;
if ([self isEnabled])
[self setImage: ejectImage];
}
-(void)setEnabled:(BOOL)enabled {
[super setEnabled: enabled];
if (_mouse) {
[self setImage: enabled ? ejectHoverImage : ejectImage];
}
}
@end

View File

@ -4,6 +4,33 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>vgm</string>
</array>
<key>CFBundleTypeName</key>
<string>Video Game Music</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSTypeIsPackage</key>
<integer>0</integer>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>vgz</string>
</array>
<key>CFBundleTypeName</key>
<string>Video Game Music</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSTypeIsPackage</key>
<integer>0</integer>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
@ -17,13 +44,15 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>release 4</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>4</string>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2020 Kelvin Sherlock. All rights reserved.</string>
<string>Copyright © 2020-2023 Kelvin Sherlock. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
@ -31,6 +60,10 @@
<key>NSSupportsAutomaticTermination</key>
<true/>
<key>NSSupportsSuddenTermination</key>
<true/>
<false/>
<key>SUFeedURL</key>
<string>https://ample.ksherlock.com/updates/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>MgYKY5J1nIJ9+C3IabG24ri2M0CuoMqP78fva2GI5BY=</string>
</dict>
</plist>

View File

@ -10,7 +10,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface LaunchWindowController : NSWindowController <NSBrowserDelegate>
@interface LaunchWindowController : NSWindowController <NSBrowserDelegate, NSMenuDelegate>
@end

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,13 @@ NS_ASSUME_NONNULL_BEGIN
@interface LogWindowController : NSWindowController <NSWindowDelegate>
#if 0
+(id)controllerForTask: (NSTask *)task;
+(id)controllerForTask: (NSTask *)task close: (BOOL)close;
#endif
+(id)controllerForArgs: (NSArray *)args;
+(id)controllerForArgs: (NSArray *)args close: (BOOL)close;
@end
NS_ASSUME_NONNULL_END

View File

@ -19,6 +19,10 @@ static NSMutableSet *LogWindows;
@implementation LogWindowController {
NSTask *_task;
NSFileHandle *_handle;
NSFont *_font;
BOOL _close;
BOOL _eof;
}
+(void)initialize {
@ -30,57 +34,154 @@ static NSMutableSet *LogWindows;
}
+(id)controllerForTask: (NSTask *)task {
+(id)controllerForTask: (NSTask *)task close: (BOOL)close {
LogWindowController *controller = [[LogWindowController alloc] initWithWindowNibName: @"LogWindow"];
[controller runTask: task];
[controller runTask: task close: close];
return controller;
}
+(id)controllerForArgs: (NSArray *)args close: (BOOL)close {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSURL *url = MameURL();
if (!url) {
NSAlert *alert = [NSAlert new];
[alert setMessageText: @"Unable to find MAME executable path"];
[alert runModal];
return nil;
}
NSTask *task = [NSTask new];
if (@available(macOS 10.13, *)) {
[task setExecutableURL: url];
[task setCurrentDirectoryURL: MameWorkingDirectory()];
} else {
[task setLaunchPath: MamePath()];
[task setCurrentDirectoryPath: MameWorkingDirectoryPath()];
}
[task setArguments: args];
if ([defaults boolForKey: kUseLogWindow] == NO) {
NSAlert *alert = nil;
if (@available(macOS 10.13, *)) {
NSError *error = nil;
[task launchAndReturnError: &error];
if (error) {
alert = [NSAlert alertWithError: error];
}
} else {
@try {
[task launch];
} @catch (NSException *exception) {
alert = [NSAlert new];
[alert setMessageText: [exception reason]];
}
}
if (alert) [alert runModal];
return nil;
}
return [LogWindowController controllerForTask: task close: close];
}
+(id)controllerForArgs: (NSArray *)args {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL close = [defaults boolForKey: kAutoCloseLogWindow];
return [self controllerForArgs: args close: close];
}
- (void)windowDidLoad {
[super windowDidLoad];
[LogWindows addObject: self];
_font = [NSFont userFixedPitchFontOfSize: 0];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
-(void)appendString: (NSString *)string
{
if ([string length])
{
[[[_textView textStorage] mutableString] appendString: string];
// needs explicit color attribute for proper dark mode support.
NSDictionary *attr = @{
NSForegroundColorAttributeName: [NSColor textColor],
NSFontAttributeName: _font,
};
NSAttributedString *astr = [[NSAttributedString alloc] initWithString: string attributes: attr];
[[_textView textStorage] appendAttributedString: astr];
}
}
-(NSError *)runTask: (NSTask *)task {
-(void)appendAttributedString: (NSAttributedString *)string {
if ([string length]) {
[[_textView textStorage] appendAttributedString: string];
}
}
-(NSError *)runTask: (NSTask *)task close: (BOOL)close {
if (_task) return nil;
_close = close;
_eof = NO;
NSError *error = nil;
NSPipe *pipe = [NSPipe pipe];
// window not yet loaded until [self window] called.
const char *path = nil;
const char *wd = nil;
[task setStandardError: pipe];
[task setStandardOutput: pipe];
[task launchAndReturnError: &error];
if (@available(macOS 10.13, *)) {
NSError *error = nil;
path = [[task executableURL] fileSystemRepresentation];
wd = [[task currentDirectoryURL] fileSystemRepresentation];
if (error) {
NSURL *url = [task executableURL];
NSString *path = [NSString stringWithCString: [url fileSystemRepresentation] encoding: NSUTF8StringEncoding];
NSLog(@"NSTask error. Path = %@ error = %@", path, error);
[self appendString: path];
[self appendString: [error description]];
return error;
[task launchAndReturnError: &error];
if (error) {
NSLog(@"NSTask error. Path = %s error = %@", path, error);
return error;
}
} else {
path = [[task launchPath] fileSystemRepresentation];
wd = [[task currentDirectoryPath] fileSystemRepresentation];
@try {
[task launch];
} @catch (NSException *exception) {
NSLog(@"NSTask exception. Path = %s exception = %@", path, exception);
return nil; // ?
}
}
_task = task;
NSString *title = [NSString stringWithFormat: @"Ample Log - %u", [task processIdentifier]];
[[self window] setTitle: title];
_handle = [pipe fileHandleForReading];
if (path) [self appendString: [NSString stringWithFormat: @"MAME path: %s\n", path]];
if (wd) [self appendString: [NSString stringWithFormat: @"Working Directory: %s\n", wd]];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver: self
selector: @selector(taskComplete:)
name: NSTaskDidTerminateNotification
@ -91,6 +192,7 @@ static NSMutableSet *LogWindows;
object: _handle];
[_handle readInBackgroundAndNotify];
[[self window] setDocumentEdited: YES];
return nil;
}
@ -103,21 +205,33 @@ static NSMutableSet *LogWindows;
// read complete, queue up another.
NSDictionary *dict = [notification userInfo];
NSData *data = [dict objectForKey: NSFileHandleNotificationDataItem];
if ([data length])
{
NSString *string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
[self appendString: string];
[_handle readInBackgroundAndNotify];
} else {
[self appendString: @"\n"]; // -listmedia sometimes causes display issues.
_eof = YES;
//[_textView setNeedsDisplay: YES]; // -listmedia sometimes weird.
}
}
-(void)taskCompleteHack {
}
/* hask! task complete may occur while output still being processed. add a delay to compensate. */
-(void)taskComplete: (NSNotification *)notification
{
if (!_eof) {
[self performSelector: @selector(taskComplete:) withObject: notification afterDelay: 0.5];
return;
}
BOOL ok = NO;
NSTaskTerminationReason reason;
int status;
@ -131,28 +245,31 @@ static NSMutableSet *LogWindows;
if (status == 0)
{
string = @"\n\n[Success]\n\n";
//string = @"\n\n[Success]\n\n";
ok = YES;
}
else string = @"\n\n[An error occurred]\n\n";
}
else
{
string = @"\n\n[Caught signal]\n\n";
string = [NSString stringWithFormat: @"\n\n[Caught signal %d (%s)]\n\n", status, strsignal(status)];
}
[self appendString: string];
if (string) {
NSDictionary *attr = @{
NSForegroundColorAttributeName: [NSColor systemRedColor],
NSFontAttributeName: _font,
};
NSAttributedString *astr = [[NSAttributedString alloc] initWithString: string attributes: attr];
[self appendAttributedString: astr];
}
_handle = nil;
_task = nil;
[[self window] setDocumentEdited: NO];
if (ok && [[NSUserDefaults standardUserDefaults] boolForKey: kAutoCloseLogWindow]) {
if (ok && _close) {
[[self window] close];
//[LogWindows removeObject: self]; // close sends WindowWillClose notification.
}
}
@ -163,4 +280,12 @@ static NSMutableSet *LogWindows;
[LogWindows removeObject: self];
}
#pragma mark - IBActions
- (IBAction)clearLog:(id)sender {
NSAttributedString *empty = [NSAttributedString new];
[[_textView textStorage] setAttributedString: empty];
}
@end

View File

@ -8,6 +8,7 @@
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "Ample.h"
NS_ASSUME_NONNULL_BEGIN
@ -17,4 +18,8 @@ NS_ASSUME_NONNULL_BEGIN
@end
@interface MachineViewController (Bookmark) <Bookmark>
@end
NS_ASSUME_NONNULL_END

View File

@ -20,11 +20,15 @@
-(void)awakeFromNib {
NSBundle *bundle = [NSBundle mainBundle];
#ifdef AMPLE_LITE
NSString *path = [bundle pathForResource: @"models~extra" ofType: @"plist"];
#else
NSString *path = [bundle pathForResource: @"models" ofType: @"plist"];
#endif
_data = [NSArray arrayWithContentsOfFile: path];
/* My Copy of XCode/Interface Builder barfs on NSBrowser. */
/* XCode/Interface Builder 11.3 barfs on NSBrowser. */
NSBrowser *browser;
NSRect frame = NSMakeRect(0, 0, 718, 200);
@ -110,5 +114,67 @@
return [data count];
}
@end
@implementation MachineViewController (Bookmark)
-(BOOL)loadBookmark: (NSDictionary *)bookmark {
NSBrowser *browser = (NSBrowser *)[self view];
NSString *machine = [bookmark objectForKey: @"machine"];
NSIndexPath *path = nil;
NSUInteger ix[2] = {0, 0 };
for (NSDictionary *d in _data) {
NSArray *children = [d objectForKey: @"children"];
for (NSDictionary *dd in children) {
NSString *value = [dd objectForKey: @"value"];
if ([machine isEqualToString: value]) {
path = [NSIndexPath indexPathWithIndexes: ix length: 2];
[browser selectRow: ix[0] inColumn: 0];
[browser selectRow: ix[1] inColumn: 1];
//[browser setSelectionIndexPath: path];
return YES;
}
++ix[1];
}
ix[1] = 0;
// check parent after.
NSString *value = [d objectForKey: @"value"];
if ([machine isEqualToString: value]) {
path = [NSIndexPath indexPathWithIndexes: ix length: 1];
[browser selectRow: ix[0] inColumn: 0];
// "setSelectionIndexPath: is not supported for browsers with matrix delegates."
//[browser setSelectionIndexPath: path];
return YES;
}
++ix[0];
}
NSLog(@"MachineViewController: Unable to find %@", machine);
return NO;
}
-(BOOL)saveBookmark: (NSMutableDictionary *)bookmark {
// machine saved in parent.
return YES;
}
-(void)willLoadBookmark:(NSDictionary *)bookmark {
}
-(void)didLoadBookmark:(NSDictionary *)bookmark {
}
@end

56
Ample/Media.h Normal file
View File

@ -0,0 +1,56 @@
//
// Media.h
// Ample
//
// Created by Kelvin Sherlock on 3/7/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#ifndef Media_h
#define Media_h
typedef struct Media {
unsigned cass;
unsigned cdrom;
unsigned hard;
unsigned floppy_8;
unsigned floppy_5_25;
unsigned floppy_3_5;
unsigned pseudo_disk;
unsigned bitbanger;
unsigned midiin;
unsigned midiout;
unsigned picture;
unsigned rom;
uint64_t floppy_mask_8;
uint64_t floppy_mask_5_25;
uint64_t floppy_mask_3_5;
} Media;
typedef enum {
MediaTypeError = -1,
MediaTypeUnknown = 0,
MediaType_8,
MediaType_5_25,
MediaType_3_5,
MediaType_HardDisk,
MediaType_CDROM,
MediaType_Cassette,
MediaType_Picture,
MediaType_MIDI,
MediaType_ROM,
} MediaType;
struct Media MediaFromDictionary(NSDictionary *);
void MediaAdd(Media *dest, const Media *src);
BOOL MediaEqual(const Media *lhs, const Media *rhs);
extern const Media EmptyMedia;
MediaType ClassifyMediaFile(id file);
#endif /* Media_h */

382
Ample/Media.m Normal file
View File

@ -0,0 +1,382 @@
//
// Media.m
// Ample
//
// Created by Kelvin Sherlock on 3/7/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Media.h"
const Media EmptyMedia = { 0 };
struct Media MediaFromDictionary(NSDictionary *dict) {
Media m = { 0 };
#define _(name) m.name = [[dict objectForKey: @ # name] unsignedIntValue]
_(cass);
_(cdrom);
_(hard);
_(floppy_3_5);
_(floppy_5_25);
_(floppy_8);
_(pseudo_disk);
_(bitbanger);
_(midiin);
_(midiout);
_(picture);
_(rom);
return m;
#undef _
}
void MediaAdd(Media *dest, const Media *src) {
if (!src || !dest) return;
// could merge from src media but not currently set there.
//unsigned count;
unsigned dest_flops = dest->floppy_8 + dest->floppy_5_25 + dest->floppy_3_5;
unsigned src_flops = src->floppy_8 || src->floppy_5_25 || src->floppy_3_5;
#define _(name) dest->name += src->name;
_(cass);
_(cdrom);
_(hard);
_(floppy_3_5);
_(floppy_5_25);
_(floppy_8);
_(pseudo_disk);
_(bitbanger);
_(midiin);
_(midiout);
_(picture);
_(rom);
#undef _
// this assumes any device that supports more than 1 floppy size
// the order is 8" < 5.25" < 3.5"
if (src_flops) {
uint64_t bits = 1 << dest_flops;
for (unsigned i = 0; i < src->floppy_8; ++i) {
dest->floppy_mask_8 |= bits;
bits <<= 1;
}
for (unsigned i = 0; i < src->floppy_5_25; ++i) {
dest->floppy_mask_5_25 |= bits;
bits <<= 1;
}
for (unsigned i = 0; i < src->floppy_3_5; ++i) {
dest->floppy_mask_3_5 |= bits;
bits <<= 1;
}
}
}
BOOL MediaEqual(const Media *lhs, const Media *rhs) {
if (lhs == rhs) return YES;
if (!lhs || !rhs) return NO;
#define _(name) if (lhs->name != rhs->name) return NO;
_(cass);
_(cdrom);
_(hard);
_(floppy_3_5);
_(floppy_5_25);
_(floppy_8);
_(pseudo_disk);
_(bitbanger);
_(midiin);
_(midiout);
_(picture);
_(rom);
_(floppy_mask_8);
_(floppy_mask_5_25);
_(floppy_mask_3_5);
return YES;
#undef _
}
#include <unistd.h>
#include <sys/stat.h>
#define _x2(a,b) (a | (b << 8))
#define _x3(a,b,c) (a | (b << 8) | (c << 16))
#define _x4(a,b,c, d) (a | (b << 8) | (c << 16) | (d << 24))
static unsigned hash(const char *cp) {
unsigned rv = 0;
int i, shift;
if (!cp) return 0;
for (i = 0, shift = 0; i < 4; ++i, shift += 8) {
unsigned c = cp[i];
if (!c) break;
c = tolower(c);
rv |= (c << shift);
}
//if (i > 4) return 0; // .image is 5....
return rv;
}
const char *extname(const char *path) {
const char *rv = NULL;
if (!path) return path;
for(unsigned i = 0; ; ++i) {
unsigned c = path[i];
if (c == 0) break;
if (c == '/') rv = NULL;
if (c == '.') rv = path + i + 1;
}
if (rv && !*rv) rv = NULL;
return rv;
}
/*
* MAME cares deeply about file extensions. LIST NOT EXHAUSTIVE
*
* Hard Disk: .chd .hd .hdv .2mg .hdi
* CD-ROM: .chd .cue .toc .nrg .gdi .iso .cdr
* 5.25: .dsk .do .po .edd .woz .nib .mfi .dfi .rti
* 3.5: .dc42 .woz .2mg .mfi .dfi .hfe .mfm .td0 .imd
.d77 .d88 .1dd .cqm .cqi .dsk .ima .img .ufi
.360 .ipf [also .po and .hdv]
* Midi in: .mid
* Midi out: .mid
* Picture: .png
* Cassette: .wav
*/
static bool is_raw_525(size_t disk_size) {
if (disk_size & 255) return NO;
size_t blocks = disk_size >> 8;
return blocks == 560 || blocks == 640;
}
static BOOL is_raw_35(size_t disk_size) {
if (disk_size & 511) return NO;
size_t blocks = disk_size >> 9;
// atari st has 360 (single sided) and 720 (double-sided) disks..
return blocks == 800 || blocks == 1600 || blocks == 1440 || blocks == 2880 || blocks == 720 || blocks == 360;
}
static MediaType is_woz(const uint8_t *buffer, size_t file_size) {
/* woz 1/2 ? */
if (!memcmp(buffer, "WOZ1\xff\x0a\x0d\x0a", 8) || !memcmp(buffer, "WOZ2\xff\x0a\x0d\x0a", 8)) {
if (!memcmp(buffer + 12, "INFO", 4)) {
unsigned type = buffer[21]; // 1 = 5.25, 2 = 3.5
if (type == 1) return MediaType_5_25;
if (type == 2) return MediaType_3_5;
}
return MediaTypeUnknown;
}
return MediaTypeError;
}
static MediaType is_dc42(const uint8_t *buffer, size_t file_size) {
if (buffer[0x52] == 0x01 && buffer[0x53] == 0x00 && buffer[0] >= 1 && buffer[0] <= 0x3f) {
int dsize = OSReadBigInt32(buffer, 0x40);
int tsize = OSReadBigInt32(buffer, 0x44);
if (dsize + tsize + 0x54 == file_size) {
if (is_raw_35(dsize)) return MediaType_3_5;
return MediaType_HardDisk;
}
}
return MediaTypeError;
}
static MediaType is_2img(const uint8_t *buffer, size_t file_size) {
if (!memcmp(buffer, "2IMG", 4)) {
int format = OSReadLittleInt32(buffer, 0x0c); // 0 - dos order, 1 = prodos order, 2 = nib data
int blocks = OSReadLittleInt32(buffer, 0x14); // prodos only.
//int bytes = OSReadLittleInt32(buffer, 0x1c);
if (format == 2 || format == 0) return MediaType_5_25; // nib and dos order
if (is_raw_525(blocks * 512)) return MediaType_5_25;
if (is_raw_35(blocks * 512)) return MediaType_3_5;
return MediaType_HardDisk; //
//return MediaTypeUnknown;
}
return MediaTypeError;
}
static MediaType is_chd(const uint8_t *buffer, size_t file_size) {
if (!memcmp(buffer, "MComprHD", 8)) {
static int offsets[] = { 0, 0, 0, 28, 28, 32}; // offset for logival bytes.
int version = OSReadBigInt32(buffer, 12);
if (version >= 3 && version <= 5) {
long bytes = OSReadBigInt64(buffer, offsets[version]);
if (is_raw_525(bytes)) return MediaType_5_25;
if (is_raw_35(bytes)) return MediaType_3_5;
return MediaType_HardDisk; // iso?
}
return MediaTypeUnknown;
}
return MediaTypeError;
}
static MediaType is_ipf(const uint8_t *buffer, size_t file_size) {
// http://justsolve.archiveteam.org/wiki/IPF
if (!memcmp(buffer, "CAPS\x00\x00\x00", 7)) return MediaType_3_5;
return MediaTypeUnknown;
}
static MediaType is_hxcf(const uint8_t *buffer, size_t file_size) {
// HxCFloppyEmulator
if (!memcmp(buffer, "HXCMFM", 6)) return MediaType_3_5;
return MediaTypeUnknown;
}
static MediaType is_msa(const uint8_t *buffer, size_t file_size) {
// Atari MSA
if (!memcmp(buffer, "\x0x\x0f", 2)) return MediaType_3_5;
return MediaTypeUnknown;
}
static MediaType is_pasti(const uint8_t *buffer, size_t file_size) {
// Atari STX/Pasti
if (!memcmp(buffer, "RSY\x00\x03\x00", 6)) return MediaType_3_5;
return MediaTypeUnknown;
}
MediaType ClassifyMediaFile(id file) {
struct stat st;
ssize_t size;
unsigned char buffer[128];
int fd;
const char *path = [file fileSystemRepresentation]; // or URL
const char *ext = extname(path);
unsigned ext_hash = hash(ext);
memset(&st, 0, sizeof(st));
memset(buffer, 0, sizeof(buffer));
fd = open(path, O_RDONLY);
if (fd < 0) return MediaTypeError;
fstat(fd, &st);
size = read(fd, buffer, sizeof(buffer));
close(fd);
if (size <= 0) return MediaTypeError;
// 13 sector support ? not on an event 512 block boundary.
// = 116480 bytes.
switch(ext_hash) {
case _x3('w', 'o', 'z'):
return is_woz(buffer, st.st_size);
case _x3('2', 'm', 'g'):
case _x4('2', 'i', 'm', 'g'):
return is_2img(buffer, st.st_size);
case _x3('c', 'h', 'd'):
return is_chd(buffer, st.st_size);
// dc42 - dc,dc42,dsk,img,image
case _x2('d', 'c'): // n.b. as of .233, allowed for mac, not for apple2
case _x4('d', 'c', '4', '2'):
return is_dc42(buffer, st.st_size);
// dsk, image, img may also be raw or disk copy.
case _x3('d', 's', 'k'):
case _x3('i', 'm', 'g'):
case _x4('i', 'm', 'a', 'g'):
if (is_raw_525(st.st_size)) return MediaType_5_25;
if (is_raw_35(st.st_size)) return MediaType_3_5;
return is_dc42(buffer, st.st_size);
case _x2('d', 'o'):
case _x2('p', 'o'):
if (is_raw_525(st.st_size)) return MediaType_5_25;
if (is_raw_35(st.st_size)) return MediaType_3_5;
return MediaTypeUnknown;
// hdv - 3.5 or hard drive.
case _x3('h', 'd', 'v'):
case _x3('r', 'a', 'w'):
if (is_raw_35(st.st_size)) return MediaType_3_5;
if ((st.st_size & 511) == 0) return MediaType_HardDisk;
return MediaTypeUnknown;
case _x3('n', 'i', 'b'):
return MediaType_5_25;
case _x3('w', 'a', 'v'):
return MediaType_Cassette;
// cd-rom
case _x3('i', 's', 'o'):
case _x3('c', 'u', 'e'):
case _x3('c', 'd', 'r'):
return MediaType_CDROM;
case _x3('p', 'n', 'g'):
return MediaType_Picture;
case _x3('m', 'i', 'd'):
return MediaType_MIDI;
// atari st, etc, 3.5 disk?
// http://justsolve.archiveteam.org/wiki/Disk_Image_Formats
case _x3('i', 'p', 'f'):
return is_ipf(buffer, st.st_size);
case _x3('m', 'f', 'm'):
return is_hxcf(buffer, st.st_size);
case _x3('m', 's', 'a'):
return is_msa(buffer, st.st_size);
case _x2('s', 't'):
if (is_raw_35(st.st_size)) return MediaType_3_5;
return MediaTypeUnknown;
case _x3('s', 't', 'x'): // pasti
return is_pasti(buffer, st.st_size);
//case _x3('m', 'f', 'i'): // mame/mess floppy image [???]
//case _x3('d', 'f', 'i'): // disc ferret image
//case _x3('h', 'f', 'e'): // ???
//case _x3('t', 'd', '0'): // teledisk - may be split across multiple files (.td1, .td2, ...)
//case _x3('i', 'm', 'd'): // imagedisk
//case _x3('d', '7', '7'): //pc-88, may have multiple disk images
//case _x3('d', '8', '8'): //fm-77, may have multiple disk images.
//case _x3('1', 'd', 'd'): // related?
//case _x3('c', 'q', 'm'): // copyQM
//case _x3('c', 'q', 'i'): // copyQM
case _x3('r', 'o', 'm'):
case _x3('b', 'i', 'n'):
return MediaType_ROM;
}
return MediaTypeUnknown;
}

View File

@ -7,29 +7,31 @@
//
#import <Cocoa/Cocoa.h>
#import "Media.h"
#import "Ample.h"
NS_ASSUME_NONNULL_BEGIN
@interface MediaViewController : NSViewController <NSOutlineViewDelegate, NSOutlineViewDataSource>
@property (weak) IBOutlet NSOutlineView *outlineView;
@property (nonatomic) NSDictionary *media;
@property (nonatomic) Media media;
@property NSArray *args;
- (IBAction)deleteAction:(id)sender;
- (IBAction)ejectAction:(id)sender;
- (IBAction)pathAction:(id)sender;
-(IBAction)resetMedia:(id)sender;
//-(void)setMedia: (NSDictionary *)media;
-(BOOL)smartRouteURL: (NSURL *)url;
-(BOOL)smartRouteFile: (NSString *)file;
@end
@interface MediaViewController (Bookmark) <Bookmark>
@end
@interface TablePathView : NSTableCellView
@property (weak) IBOutlet NSPathControl *pathControl;
@property (weak) IBOutlet NSButton *deleteButton;
@end
NS_ASSUME_NONNULL_END

File diff suppressed because it is too large Load Diff

15
Ample/Menu.h Normal file
View File

@ -0,0 +1,15 @@
//
// Menu.h
// Ample
//
// Created by Kelvin Sherlock on 10/3/2020.
// Copyright © 2020 Kelvin Sherlock. All rights reserved.
//
#ifndef Menu_h
#define Menu_h
NSFont *ItalicMenuFont(void);
NSAttributedString *ItalicMenuString(NSString *s);
#endif /* Menu_h */

27
Ample/Menu.m Normal file
View File

@ -0,0 +1,27 @@
//
// Menu.m
// Ample
//
// Created by Kelvin Sherlock on 10/3/2020.
// Copyright © 2020 Kelvin Sherlock. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
NSFont *ItalicMenuFont(void) {
NSFont *font = [NSFont menuFontOfSize: 0];
NSFontDescriptor *fd = [font fontDescriptor];
NSFontDescriptor *fd2 = [fd fontDescriptorWithSymbolicTraits: NSFontDescriptorTraitItalic];
return [NSFont fontWithDescriptor: fd2 size: [font pointSize]];
}
NSAttributedString *ItalicMenuString(NSString *s) {
static NSDictionary *attr = nil;
if (!attr) {
attr = @{
NSFontAttributeName: ItalicMenuFont()
};
}
return [[NSAttributedString alloc] initWithString: s attributes: attr];
}

25
Ample/MidiManager.h Normal file
View File

@ -0,0 +1,25 @@
//
// MidiManager.h
// Ample
//
// Created by Kelvin Sherlock on 8/6/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#ifndef MidiManager_h
#define MidiManager_h
extern NSString *kMidiSourcesChangedNotification;
extern NSString *kMidiDestinationsChangedNotification;
@interface MidiManager : NSObject
@property NSArray *sources;
@property NSArray *destinations;
+(instancetype)sharedManager;
@end
#endif /* MidiManager_h */

153
Ample/MidiManager.m Normal file
View File

@ -0,0 +1,153 @@
//
// Midi.m
// Ample
//
// Created by Kelvin Sherlock on 8/6/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreMIDI/CoreMIDI.h>
#import "MidiManager.h"
static NSArray *MidiSources(void) {
ItemCount count = MIDIGetNumberOfSources();
if (count <= 0) return @[];
NSMutableArray *rv = [NSMutableArray arrayWithCapacity: count + 1];
MIDIEndpointRef ep;
for(int i = 0; i < count; ++i) {
ep = MIDIGetSource(i);
if (!ep) continue;
// https://developer.apple.com/library/archive/qa/qa1374/_index.html
CFStringRef str = NULL;
MIDIObjectGetStringProperty(ep, kMIDIPropertyDisplayName, &str);
if (str) {
[rv addObject: (__bridge id _Nonnull)(str)];
CFRelease(str);
}
}
return rv;
}
static NSArray *MidiDestinations(void) {
ItemCount count = MIDIGetNumberOfDestinations();
if (count <= 0) return @[];
NSMutableArray *rv = [NSMutableArray arrayWithCapacity: count + 1];
MIDIEndpointRef ep;
for(int i = 0; i < count; ++i) {
ep = MIDIGetDestination(i);
if (!ep) continue;
// https://developer.apple.com/library/archive/qa/qa1374/_index.html
CFStringRef str = NULL;
MIDIObjectGetStringProperty(ep, kMIDIPropertyDisplayName, &str);
if (str) {
[rv addObject: (__bridge id _Nonnull)(str)];
CFRelease(str);
}
}
return rv;
}
NSString *kMidiSourcesChangedNotification = @"Midi Sources Changed";
NSString *kMidiDestinationsChangedNotification = @"Midi Destinations Changed";
@interface MidiManager () {
MIDIClientRef _client;
}
-(void)objectAddRemove: (const MIDIObjectAddRemoveNotification *)message;
-(void)objectPropertyChanged: (const MIDIObjectPropertyChangeNotification *)message;
@end
static MidiManager *singleton = nil;
@implementation MidiManager
-(void)awakeFromNib {
if (!singleton) singleton = self;
}
+(instancetype)sharedManager {
if (!singleton) singleton = [MidiManager new];
return singleton;
}
-(instancetype)init {
if (singleton) return singleton;
OSStatus status;
status = MIDIClientCreateWithBlock(
CFSTR("serial_midi"),
&_client,
^(const MIDINotification *message){
switch(message->messageID) {
case kMIDIMsgObjectAdded:
case kMIDIMsgObjectRemoved:
[self objectAddRemove: (const MIDIObjectAddRemoveNotification *)message];
break;
case kMIDIMsgPropertyChanged:
[self objectPropertyChanged: (const MIDIObjectPropertyChangeNotification *)message];
default:
break;
}
});
_sources = MidiSources();
_destinations = MidiDestinations();
return self;
}
-(void)objectAddRemove: (const MIDIObjectAddRemoveNotification *)message {
const MIDIObjectAddRemoveNotification *m = (const MIDIObjectAddRemoveNotification *)message;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
if (m->childType == kMIDIObjectType_Source) {
[self setSources: MidiSources()];
[nc postNotificationName: kMidiSourcesChangedNotification object: self];
}
if (m->childType == kMIDIObjectType_Destination) {
[self setDestinations: MidiDestinations()];
[nc postNotificationName: kMidiDestinationsChangedNotification object: self];
}
}
-(void)objectPropertyChanged: (const MIDIObjectPropertyChangeNotification *)message {
const MIDIObjectPropertyChangeNotification *m = (const MIDIObjectPropertyChangeNotification *)message;
if (m->propertyName == kMIDIPropertyDisplayName) {
[self setSources: MidiSources()];
[self setDestinations: MidiDestinations()];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName: kMidiSourcesChangedNotification object: self];
[nc postNotificationName: kMidiDestinationsChangedNotification object: self];
}
}
-(void)dealloc {
if (_client)
MIDIClientDispose(_client);
}
@end

View File

@ -0,0 +1,30 @@
//
// NewMachineViewController.h
// Ample
//
// Created by Kelvin Sherlock on 6/8/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "Ample.h"
NS_ASSUME_NONNULL_BEGIN
@interface NewMachineViewController : NSViewController
@property (nullable) NSString *machine;
-(void)reset;
@end
@interface NewMachineViewController (Table) <NSOutlineViewDelegate, NSOutlineViewDataSource>
@end
@interface NewMachineViewController (Bookmark) <Bookmark>
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,238 @@
//
// NewMachineViewController.m
// Ample
//
// Created by Kelvin Sherlock on 6/8/2021.
// Copyright © 2021 Kelvin Sherlock. All rights reserved.
//
#import "NewMachineViewController.h"
@interface NewMachineViewController () {
NSArray *_data;
}
@property (weak) IBOutlet NSOutlineView *outlineView;
@end
@implementation NewMachineViewController
-(void)awakeFromNib {
static unsigned first = 0;
if (first) return;
first++;
NSBundle *bundle = [NSBundle mainBundle];
#ifdef AMPLE_LITE
NSString *path = [bundle pathForResource: @"models~extra" ofType: @"plist"];
#else
NSString *path = [bundle pathForResource: @"models" ofType: @"plist"];
#endif
_data = [NSArray arrayWithContentsOfFile: path];
}
-(void)viewDidLoad {
[super viewDidLoad];
//[_outlineView reloadData];
//[_outlineView setAutosaveExpandedItems: YES];
//[_outlineView expandItem: nil expandChildren: YES];
}
#pragma mark - IBActions
- (IBAction)clickAction:(id)sender {
NSInteger row = [_outlineView clickedRow];
if (row < 0) return;
NSDictionary *item = [_outlineView itemAtRow: row];
if (!item) return;
NSString *value = [item objectForKey: @"value"];
NSArray *children = [item objectForKey: @"children"];
if (value) {
[self setMachine: value];
} else if (children) {
id ap = [_outlineView animator];
[_outlineView isItemExpanded: item] ? [ap collapseItem: item] : [ap expandItem: item];
}
}
-(void)reset {
[_outlineView deselectAll: nil];
[self setMachine: nil];
}
@end
@implementation NewMachineViewController (Table)
#if 0
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item {
return YES;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldCollapseItem:(id)item {
return NO;
}
#endif
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item {
// disclosure triangle.
if (!item) return YES;
NSArray *children = [(NSDictionary *)item objectForKey: @"children"];
return [children count] > 0;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
if (!item) return YES;
NSArray *children = [(NSDictionary *)item objectForKey: @"children"];
return [children count] > 0;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
#if 0
NSArray *children = [(NSDictionary *)item objectForKey: @"children"];
return [children count] > 0;
#else
return NO;
#endif
}
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
#if 0
NSArray *children = [(NSDictionary *)item objectForKey: @"children"];
if ([children count]) {
return [outlineView makeViewWithIdentifier: @"HeaderCell" owner: self];
}
#endif
NSTableCellView *v = [outlineView makeViewWithIdentifier: @"DataCell" owner: self];
//[v setObjectValue: item];
return v;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
if (!item) return [_data count];
NSArray *children = [(NSDictionary *)item objectForKey: @"children"];
return [children count];
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
if (item == nil) {
return [_data objectAtIndex: index];
}
NSArray *children = [(NSDictionary *)item objectForKey: @"children"];
return [children objectAtIndex: index];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
return item;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item {
if (!item) return NO;
return [(NSDictionary *)item objectForKey: @"value"] != nil;
}
// saving/restoring expanded items
- (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item {
return [item objectForKey: @"description"];
}
- (id)outlineView:(NSOutlineView *)outlineView itemForPersistentObject:(id)object {
if ([object isKindOfClass: [NSString class]]) {
for(NSDictionary *d in _data) {
if ([(NSString *)object isEqualToString: [d objectForKey: @"description"]])
return d;
}
}
return nil;
//return object;
}
@end
@implementation NewMachineViewController (Bookmark)
- (void)didLoadBookmark:(NSDictionary *)bookmark {
}
- (BOOL)loadBookmark:(NSDictionary *)bookmark {
NSString *machine = [bookmark objectForKey: @"machine"];
//NSInteger row = [_outlineView selectedRow];
if (!machine) {
[self setMachine: nil];
[_outlineView deselectAll: nil];
return NO;
}
for (NSDictionary *parent in _data) {
NSArray *children = [parent objectForKey: @"children"];
for (NSDictionary *child in children) {
if ([machine isEqualToString: [child objectForKey: @"value"]]) {
id ap = [_outlineView animator];
[ap expandItem: parent];
NSInteger row = [_outlineView rowForItem: child];
if (row >= 0) {
NSIndexSet *set = [NSIndexSet indexSetWithIndex: row];
[_outlineView selectRowIndexes: set byExtendingSelection: NO];
[_outlineView scrollRowToVisible: row];
return YES;
}
return NO;
}
}
// could also match parent.
if ([machine isEqualToString: [parent objectForKey: @"value"]]) {
NSInteger row = [_outlineView rowForItem: parent];
if (row >= 0) {
NSIndexSet *set = [NSIndexSet indexSetWithIndex: row];
[_outlineView selectRowIndexes: set byExtendingSelection: NO];
[_outlineView scrollRowToVisible: row];
return YES;
}
return NO;
}
}
return NO;
}
- (BOOL)saveBookmark:(NSMutableDictionary *)bookmark {
// machine saved in parent.
return YES;
}
- (void)willLoadBookmark:(NSDictionary *)bookmark {
}
@end

View File

@ -9,8 +9,13 @@
#import "Ample.h"
#import "PreferencesWindowController.h"
#import <Security/Security.h>
@interface PreferencesWindowController ()
@property (weak) IBOutlet NSTextField *pathField;
@property (weak) IBOutlet NSTextField *wdField;
@property (weak) IBOutlet NSButton *fixButton;
@end
@ -27,19 +32,41 @@
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
[self validateMamePath: [defaults stringForKey: kMamePath]];
[self validateMameWD: [defaults stringForKey: kMameWorkingDirectory]];
/* check vmnet_helper permissions */
int needs_fixin = [self checkHelperPermissions: nil];
[_fixButton setEnabled: needs_fixin > 0];
}
-(void)validateMamePath: (NSString *)path {
NSFileManager * fm = [NSFileManager defaultManager];
if ([path length] == 0 || [fm isExecutableFileAtPath: path]) {
[_pathField setTextColor: [NSColor blackColor]];
[_pathField setTextColor: nil];
} else {
[_pathField setTextColor: [NSColor redColor]];
[_pathField setTextColor: [NSColor systemRedColor]];
}
}
-(void)validateMameWD: (NSString *)path {
NSFileManager * fm = [NSFileManager defaultManager];
BOOL directory = YES;
if ([path length] == 0) {
[_wdField setTextColor: nil];
return;
}
if ([fm fileExistsAtPath: path isDirectory: &directory] && directory) {
[_wdField setTextColor: nil];
return;
}
[_wdField setTextColor: [NSColor systemRedColor]];
}
- (IBAction)pathChanged:(id)sender {
NSString *path = [sender stringValue];
@ -47,6 +74,126 @@
[self validateMamePath: path];
}
- (IBAction)wdChanged:(id)sender {
NSString *path = [sender stringValue];
[self validateMameWD: path];
}
// -1 - error
// 1 - needs help
// 0 - a-ok
-(int)checkHelperPermissions: (NSString *)path {
static const unsigned Mask = S_ISUID | S_ISGID;
if (!path) {
NSBundle *bundle = [NSBundle mainBundle];
path = [bundle pathForAuxiliaryExecutable: @"vmnet_helper"];
}
if (!path) return -1;
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error = nil;
NSDictionary *attr = [fm attributesOfItemAtPath: path error: &error];
if (error) return -1;
NSNumber *owner = [attr objectForKey: NSFileOwnerAccountID];
NSNumber *perm = [attr objectForKey: NSFilePosixPermissions];
if ([owner longValue] == 0 && ([perm unsignedIntValue] & Mask) == Mask) return 0;
return 1;
}
- (IBAction)fixPerms:(id)sender {
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForAuxiliaryExecutable: @"vmnet_helper"];
if (!path) return;
#if 0
// this requires an entitlement and sanboxing and Apple's permission.
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws requestAuthorizationOfType:NSWorkspaceAuthorizationTypeSetAttributes
completionHandler: ^(NSWorkspaceAuthorization *a, NSError *e){
if (e || !a) return;
NSError *error = nil;
NSDictionary *attr = @{
NSFileOwnerAccountID: @0, /* root */
NSFileGroupOwnerAccountID: @20, /* staff */
// NSFilePosixPermissions: @0106755 /* 755 + setuid + setgid */
};
NSFileManager *fm = [NSFileManager fileManagerWithAuthorization: a];
[fm setAttributes: attr ofItemAtPath: path error: &error];
if (error) {
NSLog(@"%@", error);
// NSAlert *a = [NSAlert alertWithError: error];
// [a runModal];
}
else {
[self->_fixButton setEnabled: NO];
}
}];
#endif
// AuthorizationExecuteWithPrivileges - deprecated in 10.7
// https://github.com/sveinbjornt/STPrivilegedTask
// XMJobBless + launchd stuff - the preferred way to do it...
// https://developer.apple.com/library/archive/samplecode/BetterAuthorizationSample/Introduction/Intro.html
// https://developer.apple.com/library/archive/samplecode/SMJobBless/Listings/ReadMe_txt.html#//apple_ref/doc/uid/DTS40010071-ReadMe_txt-DontLinkElementID_3
//
// really should be a launchd service but that's for another time...
AuthorizationRef myAuthorizationRef = 0;
OSStatus myStatus = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &myAuthorizationRef);
if (myStatus) return;
AuthorizationItem myItems[1] = {{0}};
myItems[0].name = kAuthorizationRightExecute;
myItems[0].valueLength = 0;
myItems[0].value = NULL;
myItems[0].flags = 0;
AuthorizationRights myRights = {0};
myRights.count = sizeof(myItems) / sizeof(myItems[0]);
myRights.items = myItems;
AuthorizationFlags myFlags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize;
myStatus = AuthorizationCopyRights(myAuthorizationRef, &myRights,
kAuthorizationEmptyEnvironment, myFlags, NULL);
if (!myStatus) {
FILE *fp = NULL;
static char buffer[4096];
const char *cp = [path fileSystemRepresentation];
const char* args_chown[] = {"root", cp , NULL};
const char* args_chmod[] = {"+s", cp, NULL};
// well ... the second command executes a lot more consistently when the (optional) fp is provided and the we fgets the buffer.
// textmate does a wait() to wait for a child to exit. Using the fp (which is popened()?) and reading until EOF
// accomplishes the same thing.
myStatus = AuthorizationExecuteWithPrivileges(myAuthorizationRef, "/usr/sbin/chown", kAuthorizationFlagDefaults, (char**)args_chown, &fp);
while (fgets(buffer, sizeof(buffer), fp));
fclose(fp);
// fprintf(stderr, "myStatus = %d\ndata: %s\n", myStatus, buffer);
myStatus = AuthorizationExecuteWithPrivileges(myAuthorizationRef, "/bin/chmod", kAuthorizationFlagDefaults, (char**)args_chmod, &fp);
while (fgets(buffer, sizeof(buffer), fp));
fclose(fp);
// fprintf(stderr, "myStatus = %d\ndata: %s\n", myStatus, buffer);
}
AuthorizationFree(myAuthorizationRef, kAuthorizationFlagDestroyRights);
int needs_fixin = [self checkHelperPermissions: path];
[_fixButton setEnabled: needs_fixin > 0];
}
@end

View File

@ -0,0 +1,231 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Keyboard Cheat Sheet</title>
<style type="text/css">
:root {
color-scheme: light dark;
font-family: -apple-system, 'HelveticaNeue' ;
font: -apple-system-body;
}
body {
user-select: none;
background-color: rgb(236, 236, 236);
color: rgb(38, 38, 38);
}
h1, h2 {
text-align: center;
font-size: 150%;
}
table {
width: 100%;
}
kbd {
display: inline-block;
border-radius: 3px;
padding-left: .5em;
padding-right: .5em;
padding-top: 4px;
padding-bottom: 2px;
margin-bottom: 5px;
margin-right: 5px;
margin-left: 4px;
border: solid 1px black;
box-shadow: 1px 1px 2px 0px rgba(0,0,0,0.75), inset 1px 1px 2px 0px white;
text-shadow: 0px 1px 0px rgb(255, 255, 255);
background-color: rgb(225, 225, 225);
}
@media (prefers-color-scheme: dark) {
body {
background-color: rgb(50, 50, 50);
color: rgb(225, 225, 225);
}
kbd {
border: solid 1px black;
text-shadow: 0px 1px 0px black;
box-shadow: 1px 1px 2px 0px rgba(0,0,0,0.75);
background-color: rgb(101, 101, 101);
}
}
</style>
<script type="text/javascript">
/* os x 10.11 */
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = Array.prototype.forEach;
}
function macbook(onoff) {
var nodes = document.querySelectorAll("[data-macbook]");
nodes.forEach( function(e) {
var m = (e.dataset.macbook == "true");
e.hidden = m ^ onoff;
});
}
window.addEventListener('load', function(event) {
macbook(false);
var e = document.getElementById('macbook');
if (e) {
e.checked = false;
e.addEventListener('click', function (event) {
macbook(e.checked);
});
}
})
</script>
</head>
<body>
<div>
MacBook: <input type="checkbox" id="macbook" />
</div>
<h1>Full UI Mode</h1>
<table>
<colgroup>
<col style="width: 14em;" />
<col />
</colgroup>
<tbody>
<tr>
<td>
<span data-macbook=false><kbd>Delete</kbd></span>
<span data-macbook=true><kbd>Fn</kbd>+<kbd>Delete</kbd></span>
</td>
<td>Toggle partial UI mode</td>
</tr>
<tr>
<td><kbd>Option</kbd>+<kbd>Enter</kbd></td>
<td>Toggle full screen mode</td>
</tr>
<tr>
<td>
<span data-macbook=false><kbd>F12</kbd></span>
<span data-macbook=true><kbd>Fn</kbd>+<kbd>F12</kbd></span>
</td>
<td>Reset Key</td>
</tr>
</tbody>
</table>
<h1>Partial UI Mode</h1>
<table>
<colgroup>
<col style="width: 14em;" />
<col />
</colgroup>
<tbody>
<tr>
<td>
<span data-macbook=false><kbd>Delete</kbd></span>
<span data-macbook=true><kbd>Fn</kbd>+<kbd>Delete</kbd></span>
</td>
<td>Toggle full UI mode</td>
</tr>
<tr>
<td><kbd>Option</kbd>+<kbd>Enter</kbd></td>
<td>Toggle full screen mode</td>
</tr>
<tr>
<td><kbd>Tab</kbd></td>
<td>Config menu</td>
</tr>
<tr>
<td><kbd>Esc</kbd></td>
<td>Quit</td>
</tr>
<tr>
<td><kbd>F5</kbd></td>
<td>Pause</td>
</tr>
<tr>
<td><kbd>~</kbd></td>
<td>Debugger break (when active)</td>
</tr>
<tr>
<td>
<span data-macbook=false><kbd>Page Down</kbd></span>
<span data-macbook=true><kbd>Fn</kbd>+<kbd>Down Arrow</kbd></span>
</td>
<td>Fast forward (while pressed)</td>
</tr>
<tr>
<td><kbd>F3</kbd></td>
<td>Soft reset</td>
</tr>
<tr>
<td><kbd>Shift</kbd>+<kbd>F3</kbd></td>
<td>Hard reset</td>
</tr>
<!--
<tr>
<td><kbd>F5</kbd></td>
<td>Toggle debugger</td>
</tr>
<tr>
<td><kbd>Shift</kbd>+<kbd>F5</kbd></td>
<td>Toggle graphic filters</td>
</tr>
-->
<tr>
<td><kbd>Shift</kbd>+<kbd>F6</kbd></td>
<td>Create save state</td>
</tr>
<tr>
<td><kbd>F7</kbd></td>
<td>Load save state</td>
</tr>
<tr>
<td><kbd>F10</kbd></td>
<td>Toggle throttle</td>
</tr>
<tr>
<td><kbd>F11</kbd></td>
<td>Show FPS</td>
</tr>
<tr>
<td><kbd>Shift</kbd>+<kbd>F11</kbd></td>
<td>Show profiler</td>
</tr>
<tr>
<td><kbd>F12</kbd></td>
<td>Save snapshot</td>
</tr>
<tr>
<td><kbd>Shift</kbd>+<kbd>F12</kbd></td>
<td>Record MNG video</td>
</tr>
<tr>
<td><kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>F12</kbd></td>
<td>Record AVI video</td>
</tr>
<tr>
<td><kbd>Option</kbd>+<kbd>Shift</kbd>+<kbd>F12</kbd></td>
<td>Record rendered AVI video</td>
</tr>
</tbody>
</table>
<h2>Note</h2>
<ul class="note">
<li><kbd>F</kbd> keys may require <kbd>Fn</kbd> key depending on keyboard and system settings.</li>
<li><kbd>Shift</kbd>, <kbd>Control</kbd>, and <kbd>Option</kbd> assume left-key unless otherwise specified.</li>
</ul>
</body>
</html>

875
Ample/Resources/a1000.plist Normal file
View File

@ -0,0 +1,875 @@
<?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>value</key>
<string>a1000</string>
<key>description</key>
<string>Amiga 1000 (PAL)</string>
<key>media</key>
<dict>
</dict>
<key>resolution</key>
<array>
<integer>724</integer>
<integer>567</integer>
</array>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>smartport</string>
<key>description</key>
<string>Disk Drives</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string></string>
<key>devname</key>
<string>smartport</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>rs232</string>
<key>description</key>
<string>Serial</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>devname</key>
<string>ie15_terminal</string>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>devname</key>
<string>scorpion_ic</string>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>devname</key>
<string>pseudo_terminal</string>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>devname</key>
<string>rs_serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>devname</key>
<string>rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>devname</key>
<string>dec_rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>devname</key>
<string>null_modem</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>devname</key>
<string>rs232_patch_box</string>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>devname</key>
<string>rs232_sync_io</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>devname</key>
<string>serial_keyboard</string>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>devname</key>
<string>serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>devname</key>
<string>serial_terminal</string>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>devname</key>
<string>sunkbd_adaptor</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>devname</key>
<string>mockingboardd</string>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>devname</key>
<string>swtpc8212_terminal</string>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>centronics</string>
<key>description</key>
<string>Printer</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Centronics Printer</string>
<key>default</key>
<true/>
<key>devname</key>
<string>centronics_printer</string>
</dict>
<dict>
<key>value</key>
<string>pl80</string>
<key>description</key>
<string>COMX PL-80</string>
<key>devname</key>
<string>comx_pl80</string>
</dict>
<dict>
<key>value</key>
<string>covox_stereo</string>
<key>description</key>
<string>Covox (Stereo-in-1)</string>
<key>devname</key>
<string>covox_stereo</string>
</dict>
<dict>
<key>value</key>
<string>covox</string>
<key>description</key>
<string>Covox Speech Thing</string>
<key>devname</key>
<string>covox</string>
</dict>
<dict>
<key>value</key>
<string>digiblst</string>
<key>description</key>
<string>Digiblaster (DIY)</string>
<key>devname</key>
<string>cpcdigiblst</string>
</dict>
<dict>
<key>value</key>
<string>ap2000</string>
<key>description</key>
<string>Epson ActionPrinter 2000</string>
<key>devname</key>
<string>ap2000</string>
</dict>
<dict>
<key>value</key>
<string>ex800</string>
<key>description</key>
<string>Epson EX-800</string>
<key>devname</key>
<string>ex800</string>
</dict>
<dict>
<key>value</key>
<string>lx800</string>
<key>description</key>
<string>Epson LX-800</string>
<key>devname</key>
<string>lx800</string>
</dict>
<dict>
<key>value</key>
<string>lx810l</string>
<key>description</key>
<string>Epson LX-810L</string>
<key>devname</key>
<string>lx810l</string>
</dict>
<dict>
<key>value</key>
<string>p72</string>
<key>description</key>
<string>NEC PinWriter P72</string>
<key>devname</key>
<string>p72</string>
</dict>
<dict>
<key>value</key>
<string>samdac</string>
<key>description</key>
<string>SAMDAC</string>
<key>devname</key>
<string>centronics_samdac</string>
</dict>
<dict>
<key>value</key>
<string>nlq401</string>
<key>description</key>
<string>Schneider NLQ 401 Matrix Printer</string>
<key>devname</key>
<string>nlq401</string>
</dict>
<dict>
<key>value</key>
<string>chessmec</string>
<key>description</key>
<string>Tasc ChessMachine EC Interface</string>
<key>devname</key>
<string>centronics_chessmec</string>
</dict>
<dict>
<key>value</key>
<string>smartboard</string>
<key>description</key>
<string>Tasc SmartBoard SB30 Interface</string>
<key>devname</key>
<string>centronics_smartboard</string>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>kbd</string>
<key>description</key>
<string>Keyboard</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a1000_dk</string>
<key>description</key>
<string>Amiga 1000 Keyboard (Denmark)</string>
<key>devname</key>
<string>a1000kbd_dk</string>
</dict>
<dict>
<key>value</key>
<string>a1000_fr</string>
<key>description</key>
<string>Amiga 1000 Keyboard (France/Belgium)</string>
<key>devname</key>
<string>a1000kbd_fr</string>
</dict>
<dict>
<key>value</key>
<string>a1000_de</string>
<key>description</key>
<string>Amiga 1000 Keyboard (Germany/Austria)</string>
<key>devname</key>
<string>a1000kbd_de</string>
</dict>
<dict>
<key>value</key>
<string>a1000_it</string>
<key>description</key>
<string>Amiga 1000 Keyboard (Italy)</string>
<key>devname</key>
<string>a1000kbd_it</string>
</dict>
<dict>
<key>value</key>
<string>a1000_se</string>
<key>description</key>
<string>Amiga 1000 Keyboard (Sweden/Finland)</string>
<key>devname</key>
<string>a1000kbd_se</string>
</dict>
<dict>
<key>value</key>
<string>a1000_us</string>
<key>description</key>
<string>Amiga 1000 Keyboard (U.S./Canada)</string>
<key>default</key>
<true/>
<key>devname</key>
<string>a1000kbd_us</string>
</dict>
<dict>
<key>value</key>
<string>a1000_gb</string>
<key>description</key>
<string>Amiga 1000 Keyboard (UK)</string>
<key>devname</key>
<string>a1000kbd_gb</string>
</dict>
<dict>
<key>value</key>
<string>a1200_us</string>
<key>description</key>
<string>Amiga 1200 Keyboard Rev B</string>
<key>devname</key>
<string>a1200kbd_rb</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_dk</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - Denmark)</string>
<key>devname</key>
<string>a2000kbd_g80_dk</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_de</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - Germany/Austria)</string>
<key>devname</key>
<string>a2000kbd_g80_de</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_se</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - Sweden/Finland)</string>
<key>devname</key>
<string>a2000kbd_g80_se</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_us</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - U.S./Canada)</string>
<key>devname</key>
<string>a2000kbd_g80_us</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_gb</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - UK)</string>
<key>devname</key>
<string>a2000kbd_g80_gb</string>
</dict>
<dict>
<key>value</key>
<string>a2000_dk</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Denmark)</string>
<key>devname</key>
<string>a2000kbd_dk</string>
</dict>
<dict>
<key>value</key>
<string>a2000_fr</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (France/Belgium)</string>
<key>devname</key>
<string>a2000kbd_fr</string>
</dict>
<dict>
<key>value</key>
<string>a2000_de</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Germany/Austria)</string>
<key>devname</key>
<string>a2000kbd_de</string>
</dict>
<dict>
<key>value</key>
<string>a2000_it</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Italy)</string>
<key>devname</key>
<string>a2000kbd_it</string>
</dict>
<dict>
<key>value</key>
<string>a2000_no</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Norway)</string>
<key>devname</key>
<string>a2000kbd_no</string>
</dict>
<dict>
<key>value</key>
<string>a2000_es</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Spain)</string>
<key>devname</key>
<string>a2000kbd_es</string>
</dict>
<dict>
<key>value</key>
<string>a2000_se</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Sweden/Finland)</string>
<key>devname</key>
<string>a2000kbd_se</string>
</dict>
<dict>
<key>value</key>
<string>a2000_ch</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Switzerland)</string>
<key>devname</key>
<string>a2000kbd_ch</string>
</dict>
<dict>
<key>value</key>
<string>a2000_us</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (U.S./Canada)</string>
<key>devname</key>
<string>a2000kbd_us</string>
</dict>
<dict>
<key>value</key>
<string>a2000_gb</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (UK)</string>
<key>devname</key>
<string>a2000kbd_gb</string>
</dict>
</array>
</dict>
</array>
<key>devices</key>
<array>
<dict>
<key>name</key>
<string>smartport</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>fdc:0</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>35dd</string>
<key>description</key>
<string>3.5" DD</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>floppy_3_5</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>fdc:1</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>35dd</string>
<key>description</key>
<string>3.5" DD</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>floppy_3_5</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>fdc:2</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>35dd</string>
<key>description</key>
<string>3.5" DD</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>floppy_3_5</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>fdc:3</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>35dd</string>
<key>description</key>
<string>3.5" DD</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>floppy_3_5</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>rs232_patch_box</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:dce</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>sunkbd_adaptor</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:keyboard</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>type3hle</string>
<key>description</key>
<string>Sun Type 3 Keyboard (HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type4hle</string>
<key>description</key>
<string>Sun Type 4 Keyboard (HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5gbhle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Great Britain - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5jphle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Japan - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5sehle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Sweden - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5hle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (U.S.A. - HLE)</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
</array>
<key>software</key>
<array>
<string>amiga_workbench.xml</string>
<string>amiga_hardware.xml</string>
<string>amiga_apps.xml</string>
<string>amiga_flop.xml</string>
<string>amigaocs_flop.xml</string>
<string>amiga_demos.xml</string>
<string>amiga_a1000.xml</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,875 @@
<?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>value</key>
<string>a1000n</string>
<key>description</key>
<string>Amiga 1000 (NTSC)</string>
<key>media</key>
<dict>
</dict>
<key>resolution</key>
<array>
<integer>724</integer>
<integer>483</integer>
</array>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>smartport</string>
<key>description</key>
<string>Disk Drives</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string></string>
<key>devname</key>
<string>smartport</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>rs232</string>
<key>description</key>
<string>Serial</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>devname</key>
<string>ie15_terminal</string>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>devname</key>
<string>scorpion_ic</string>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>devname</key>
<string>pseudo_terminal</string>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>devname</key>
<string>rs_serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>devname</key>
<string>rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>devname</key>
<string>dec_rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>devname</key>
<string>null_modem</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>devname</key>
<string>rs232_patch_box</string>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>devname</key>
<string>rs232_sync_io</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>devname</key>
<string>serial_keyboard</string>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>devname</key>
<string>serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>devname</key>
<string>serial_terminal</string>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>devname</key>
<string>sunkbd_adaptor</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>devname</key>
<string>mockingboardd</string>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>devname</key>
<string>swtpc8212_terminal</string>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>centronics</string>
<key>description</key>
<string>Printer</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Centronics Printer</string>
<key>default</key>
<true/>
<key>devname</key>
<string>centronics_printer</string>
</dict>
<dict>
<key>value</key>
<string>pl80</string>
<key>description</key>
<string>COMX PL-80</string>
<key>devname</key>
<string>comx_pl80</string>
</dict>
<dict>
<key>value</key>
<string>covox_stereo</string>
<key>description</key>
<string>Covox (Stereo-in-1)</string>
<key>devname</key>
<string>covox_stereo</string>
</dict>
<dict>
<key>value</key>
<string>covox</string>
<key>description</key>
<string>Covox Speech Thing</string>
<key>devname</key>
<string>covox</string>
</dict>
<dict>
<key>value</key>
<string>digiblst</string>
<key>description</key>
<string>Digiblaster (DIY)</string>
<key>devname</key>
<string>cpcdigiblst</string>
</dict>
<dict>
<key>value</key>
<string>ap2000</string>
<key>description</key>
<string>Epson ActionPrinter 2000</string>
<key>devname</key>
<string>ap2000</string>
</dict>
<dict>
<key>value</key>
<string>ex800</string>
<key>description</key>
<string>Epson EX-800</string>
<key>devname</key>
<string>ex800</string>
</dict>
<dict>
<key>value</key>
<string>lx800</string>
<key>description</key>
<string>Epson LX-800</string>
<key>devname</key>
<string>lx800</string>
</dict>
<dict>
<key>value</key>
<string>lx810l</string>
<key>description</key>
<string>Epson LX-810L</string>
<key>devname</key>
<string>lx810l</string>
</dict>
<dict>
<key>value</key>
<string>p72</string>
<key>description</key>
<string>NEC PinWriter P72</string>
<key>devname</key>
<string>p72</string>
</dict>
<dict>
<key>value</key>
<string>samdac</string>
<key>description</key>
<string>SAMDAC</string>
<key>devname</key>
<string>centronics_samdac</string>
</dict>
<dict>
<key>value</key>
<string>nlq401</string>
<key>description</key>
<string>Schneider NLQ 401 Matrix Printer</string>
<key>devname</key>
<string>nlq401</string>
</dict>
<dict>
<key>value</key>
<string>chessmec</string>
<key>description</key>
<string>Tasc ChessMachine EC Interface</string>
<key>devname</key>
<string>centronics_chessmec</string>
</dict>
<dict>
<key>value</key>
<string>smartboard</string>
<key>description</key>
<string>Tasc SmartBoard SB30 Interface</string>
<key>devname</key>
<string>centronics_smartboard</string>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>kbd</string>
<key>description</key>
<string>Keyboard</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a1000_dk</string>
<key>description</key>
<string>Amiga 1000 Keyboard (Denmark)</string>
<key>devname</key>
<string>a1000kbd_dk</string>
</dict>
<dict>
<key>value</key>
<string>a1000_fr</string>
<key>description</key>
<string>Amiga 1000 Keyboard (France/Belgium)</string>
<key>devname</key>
<string>a1000kbd_fr</string>
</dict>
<dict>
<key>value</key>
<string>a1000_de</string>
<key>description</key>
<string>Amiga 1000 Keyboard (Germany/Austria)</string>
<key>devname</key>
<string>a1000kbd_de</string>
</dict>
<dict>
<key>value</key>
<string>a1000_it</string>
<key>description</key>
<string>Amiga 1000 Keyboard (Italy)</string>
<key>devname</key>
<string>a1000kbd_it</string>
</dict>
<dict>
<key>value</key>
<string>a1000_se</string>
<key>description</key>
<string>Amiga 1000 Keyboard (Sweden/Finland)</string>
<key>devname</key>
<string>a1000kbd_se</string>
</dict>
<dict>
<key>value</key>
<string>a1000_us</string>
<key>description</key>
<string>Amiga 1000 Keyboard (U.S./Canada)</string>
<key>default</key>
<true/>
<key>devname</key>
<string>a1000kbd_us</string>
</dict>
<dict>
<key>value</key>
<string>a1000_gb</string>
<key>description</key>
<string>Amiga 1000 Keyboard (UK)</string>
<key>devname</key>
<string>a1000kbd_gb</string>
</dict>
<dict>
<key>value</key>
<string>a1200_us</string>
<key>description</key>
<string>Amiga 1200 Keyboard Rev B</string>
<key>devname</key>
<string>a1200kbd_rb</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_dk</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - Denmark)</string>
<key>devname</key>
<string>a2000kbd_g80_dk</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_de</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - Germany/Austria)</string>
<key>devname</key>
<string>a2000kbd_g80_de</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_se</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - Sweden/Finland)</string>
<key>devname</key>
<string>a2000kbd_g80_se</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_us</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - U.S./Canada)</string>
<key>devname</key>
<string>a2000kbd_g80_us</string>
</dict>
<dict>
<key>value</key>
<string>a2000_g80_gb</string>
<key>description</key>
<string>Amiga 2000 Keyboard (Cherry - UK)</string>
<key>devname</key>
<string>a2000kbd_g80_gb</string>
</dict>
<dict>
<key>value</key>
<string>a2000_dk</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Denmark)</string>
<key>devname</key>
<string>a2000kbd_dk</string>
</dict>
<dict>
<key>value</key>
<string>a2000_fr</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (France/Belgium)</string>
<key>devname</key>
<string>a2000kbd_fr</string>
</dict>
<dict>
<key>value</key>
<string>a2000_de</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Germany/Austria)</string>
<key>devname</key>
<string>a2000kbd_de</string>
</dict>
<dict>
<key>value</key>
<string>a2000_it</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Italy)</string>
<key>devname</key>
<string>a2000kbd_it</string>
</dict>
<dict>
<key>value</key>
<string>a2000_no</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Norway)</string>
<key>devname</key>
<string>a2000kbd_no</string>
</dict>
<dict>
<key>value</key>
<string>a2000_es</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Spain)</string>
<key>devname</key>
<string>a2000kbd_es</string>
</dict>
<dict>
<key>value</key>
<string>a2000_se</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Sweden/Finland)</string>
<key>devname</key>
<string>a2000kbd_se</string>
</dict>
<dict>
<key>value</key>
<string>a2000_ch</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (Switzerland)</string>
<key>devname</key>
<string>a2000kbd_ch</string>
</dict>
<dict>
<key>value</key>
<string>a2000_us</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (U.S./Canada)</string>
<key>devname</key>
<string>a2000kbd_us</string>
</dict>
<dict>
<key>value</key>
<string>a2000_gb</string>
<key>description</key>
<string>Amiga 2000/3000/4000 Keyboard (UK)</string>
<key>devname</key>
<string>a2000kbd_gb</string>
</dict>
</array>
</dict>
</array>
<key>devices</key>
<array>
<dict>
<key>name</key>
<string>smartport</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>fdc:0</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>35dd</string>
<key>description</key>
<string>3.5" DD</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>floppy_3_5</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>fdc:1</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>35dd</string>
<key>description</key>
<string>3.5" DD</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>floppy_3_5</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>fdc:2</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>35dd</string>
<key>description</key>
<string>3.5" DD</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>floppy_3_5</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>fdc:3</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>35dd</string>
<key>description</key>
<string>3.5" DD</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>floppy_3_5</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>rs232_patch_box</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:dce</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>sunkbd_adaptor</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:keyboard</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>type3hle</string>
<key>description</key>
<string>Sun Type 3 Keyboard (HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type4hle</string>
<key>description</key>
<string>Sun Type 4 Keyboard (HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5gbhle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Great Britain - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5jphle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Japan - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5sehle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Sweden - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5hle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (U.S.A. - HLE)</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
</array>
<key>software</key>
<array>
<string>amiga_workbench.xml</string>
<string>amiga_hardware.xml</string>
<string>amiga_apps.xml</string>
<string>amiga_flop.xml</string>
<string>amigaocs_flop.xml</string>
<string>amiga_demos.xml</string>
<string>amiga_a1000.xml</string>
</array>
</dict>
</plist>

3002
Ample/Resources/a2000.plist Normal file

File diff suppressed because it is too large Load Diff

3002
Ample/Resources/a2000n.plist Normal file

File diff suppressed because it is too large Load Diff

1255
Ample/Resources/a500.plist Normal file

File diff suppressed because it is too large Load Diff

1255
Ample/Resources/a500n.plist Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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,575 @@
<?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>value</key>
<string>ace500</string>
<key>description</key>
<string>Franklin ACE 500</string>
<key>media</key>
<dict>
</dict>
<key>resolution</key>
<array>
<integer>560</integer>
<integer>192</integer>
</array>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>ramsize</string>
<key>description</key>
<string>RAM</string>
<key>options</key>
<array>
<dict>
<key>intValue</key>
<integer>131072</integer>
<key>description</key>
<string>128K</string>
<key>value</key>
<string>128K</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>smartport</string>
<key>description</key>
<string>Disk Drives</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string></string>
<key>devname</key>
<string>smartport</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>gameio</string>
<key>description</key>
<string>Game I/O</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>joy</string>
<key>description</key>
<string>Apple II Analog Joysticks</string>
<key>devname</key>
<string>a2joy</string>
</dict>
<dict>
<key>value</key>
<string>paddles</string>
<key>description</key>
<string>Apple II Paddles</string>
<key>devname</key>
<string>a2pdls</string>
</dict>
<dict>
<key>value</key>
<string>compeyes</string>
<key>description</key>
<string>Digital Vision ComputerEyes</string>
<key>devname</key>
<string>a2ceyes</string>
<key>media</key>
<dict>
<key>picture</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>gizmo</string>
<key>description</key>
<string>HAL Labs Gizmo</string>
<key>devname</key>
<string>a2gizmo</string>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>modem</string>
<key>description</key>
<string>Modem</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>devname</key>
<string>ie15_terminal</string>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>devname</key>
<string>scorpion_ic</string>
</dict>
<dict>
<key>value</key>
<string>nss_tvi</string>
<key>description</key>
<string>Novag Super System TV Interface</string>
<key>devname</key>
<string>nss_tvinterface</string>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>devname</key>
<string>pseudo_terminal</string>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>devname</key>
<string>rs_serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>devname</key>
<string>rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>devname</key>
<string>dec_rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>devname</key>
<string>null_modem</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>devname</key>
<string>rs232_patch_box</string>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>devname</key>
<string>rs232_sync_io</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>devname</key>
<string>serial_keyboard</string>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>devname</key>
<string>serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>devname</key>
<string>serial_terminal</string>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>devname</key>
<string>sunkbd_adaptor</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>devname</key>
<string>mockingboardd</string>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>devname</key>
<string>swtpc8212_terminal</string>
</dict>
</array>
</dict>
</array>
<key>devices</key>
<array>
<dict>
<key>name</key>
<string>smartport</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>sl6:0</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>525</string>
<key>description</key>
<string>5.25"</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>floppy_5_25</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>sl6:1</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>525</string>
<key>description</key>
<string>5.25"</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>floppy_5_25</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>rs232_patch_box</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:dce</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>nss_tvi</string>
<key>description</key>
<string>Novag Super System TV Interface</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>sunkbd_adaptor</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:keyboard</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>type3hle</string>
<key>description</key>
<string>Sun Type 3 Keyboard (HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type4hle</string>
<key>description</key>
<string>Sun Type 4 Keyboard (HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5gbhle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Great Britain - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5jphle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Japan - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5sehle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Sweden - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5hle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (U.S.A. - HLE)</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
</array>
<key>software</key>
<array>
<string>apple2_flop_clcracked.xml</string>
<dict>
<key>name</key>
<string>apple2_flop_orig.xml</string>
<key>filter</key>
<string>A2C</string>
</dict>
<string>apple2_flop_misc.xml</string>
</array>
</dict>
</plist>

View File

@ -6,348 +6,661 @@
<string>agat7</string>
<key>description</key>
<string>Agat-7</string>
<key>ram</key>
<array>
<dict>
<key>value</key>
<integer>32768</integer>
<key>description</key>
<string>32K</string>
<key>default</key>
<true/>
</dict>
</array>
<key>media</key>
<dict>
<key>flop_5_25</key>
<integer>2</integer>
<key>cass</key>
<integer>1</integer>
</dict>
<key>resolution</key>
<array>
<integer>512</integer>
<integer>512</integer>
<integer>256</integer>
</array>
<key>sl2</key>
<key>slots</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>name</key>
<string>ramsize</string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
<string>RAM</string>
<key>options</key>
<array>
<dict>
<key>intValue</key>
<integer>32768</integer>
<key>description</key>
<string>32K</string>
<key>value</key>
<string>32K</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>name</key>
<string>bios</string>
<key>description</key>
<string>Agat 840K floppy card</string>
<key>default</key>
<false/>
<string>ROM</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—Default—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>v1</string>
<key>description</key>
<string>Version 1</string>
</dict>
<dict>
<key>value</key>
<string>v2</string>
<key>description</key>
<string>Version 2</string>
</dict>
<dict>
<key>value</key>
<string>debug</string>
<key>description</key>
<string>Debug</string>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>name</key>
<string>sl2</string>
<key>description</key>
<string>Agat 840K floppy controller card</string>
<key>default</key>
<false/>
<string>Slot 2</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K Floppy Card</string>
<key>devname</key>
<string>agat840k_hle</string>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K Floppy Controller Card</string>
<key>devname</key>
<string>agat_fdc</string>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K Floppy Card</string>
<key>devname</key>
<string>agat7_flop</string>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>default</key>
<true/>
<key>devname</key>
<string>a7lang</string>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>devname</key>
<string>a7ram</string>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>devname</key>
<string>a7ports</string>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>name</key>
<string>sl3</string>
<key>description</key>
<string>Agat-7 140K floppy card</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>flop_5_25</key>
<integer>2</integer>
</dict>
<string>Slot 3</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K Floppy Card</string>
<key>devname</key>
<string>agat840k_hle</string>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K Floppy Controller Card</string>
<key>devname</key>
<string>agat_fdc</string>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K Floppy Card</string>
<key>default</key>
<true/>
<key>devname</key>
<string>agat7_flop</string>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>devname</key>
<string>a7lang</string>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>devname</key>
<string>a7ram</string>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>devname</key>
<string>a7ports</string>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>name</key>
<string>sl4</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>default</key>
<true/>
<string>Slot 4</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K Floppy Card</string>
<key>devname</key>
<string>agat840k_hle</string>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K Floppy Controller Card</string>
<key>devname</key>
<string>agat_fdc</string>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K Floppy Card</string>
<key>devname</key>
<string>agat7_flop</string>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>devname</key>
<string>a7lang</string>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>devname</key>
<string>a7ram</string>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>default</key>
<true/>
<key>devname</key>
<string>a7ports</string>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>name</key>
<string>sl5</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>default</key>
<false/>
<string>Slot 5</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K Floppy Card</string>
<key>devname</key>
<string>agat840k_hle</string>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K Floppy Controller Card</string>
<key>devname</key>
<string>agat_fdc</string>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K Floppy Card</string>
<key>devname</key>
<string>agat7_flop</string>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>devname</key>
<string>a7lang</string>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>devname</key>
<string>a7ram</string>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>devname</key>
<string>a7ports</string>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>name</key>
<string>sl6</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>default</key>
<false/>
<string>Slot 6</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K Floppy Card</string>
<key>devname</key>
<string>agat840k_hle</string>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K Floppy Controller Card</string>
<key>devname</key>
<string>agat_fdc</string>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K Floppy Card</string>
<key>devname</key>
<string>agat7_flop</string>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>devname</key>
<string>a7lang</string>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>default</key>
<true/>
<key>devname</key>
<string>a7ram</string>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>devname</key>
<string>a7ports</string>
</dict>
</array>
</dict>
</array>
<key>sl3</key>
<key>devices</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K floppy card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K floppy controller card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K floppy card</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>flop_5_25</key>
<integer>2</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<key>name</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>default</key>
<false/>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:centronics</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Centronics Printer</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>pl80</string>
<key>description</key>
<string>COMX PL-80</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>covox_stereo</string>
<key>description</key>
<string>Covox (Stereo-in-1)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>covox</string>
<key>description</key>
<string>Covox Speech Thing</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>digiblst</string>
<key>description</key>
<string>Digiblaster (DIY)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>ap2000</string>
<key>description</key>
<string>Epson ActionPrinter 2000</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>ex800</string>
<key>description</key>
<string>Epson EX-800</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>lx800</string>
<key>description</key>
<string>Epson LX-800</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>lx810l</string>
<key>description</key>
<string>Epson LX-810L</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>p72</string>
<key>description</key>
<string>NEC PinWriter P72</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>samdac</string>
<key>description</key>
<string>SAMDAC</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>nlq401</string>
<key>description</key>
<string>Schneider NLQ 401 Matrix Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>chessmec</string>
<key>description</key>
<string>Tasc ChessMachine EC Interface</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>smartboard</string>
<key>description</key>
<string>Tasc SmartBoard SB30 Interface</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>agat7_flop</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:0</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>525</string>
<key>description</key>
<string>5.25"</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>floppy_5_25</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>:1</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>525</string>
<key>description</key>
<string>5.25"</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>floppy_5_25</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>agat_fdc</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:0</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>525dsqd</string>
<key>description</key>
<string>5.25" quad density floppy drive</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>:1</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>525dsqd</string>
<key>description</key>
<string>5.25" quad density floppy drive</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
</array>
</dict>
</array>
<key>sl4</key>
<key>software</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K floppy card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K floppy controller card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K floppy card</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>flop_5_25</key>
<integer>2</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>default</key>
<true/>
</dict>
</array>
<key>sl5</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K floppy card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K floppy controller card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K floppy card</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>flop_5_25</key>
<integer>2</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>default</key>
<false/>
</dict>
</array>
<key>sl6</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdchle</string>
<key>description</key>
<string>Agat 840K floppy card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a9fdc</string>
<key>description</key>
<string>Agat 840K floppy controller card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7fdc</string>
<key>description</key>
<string>Agat-7 140K floppy card</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>flop_5_25</key>
<integer>2</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>a7lang</string>
<key>description</key>
<string>Agat-7 32K Language Card</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>a7ram</string>
<key>description</key>
<string>Agat-7 32K RAM Card</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>a7ports</string>
<key>description</key>
<string>Agat-7 Ports Card</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,151 +6,329 @@
<string>apple1</string>
<key>description</key>
<string>Apple I</string>
<key>ram</key>
<array>
<dict>
<key>value</key>
<integer>4096</integer>
<key>description</key>
<string>4K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>8192</integer>
<key>description</key>
<string>8K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>12288</integer>
<key>description</key>
<string>12K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>16384</integer>
<key>description</key>
<string>16K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>20480</integer>
<key>description</key>
<string>20K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>24576</integer>
<key>description</key>
<string>24K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>28672</integer>
<key>description</key>
<string>28K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>32768</integer>
<key>description</key>
<string>32K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>36864</integer>
<key>description</key>
<string>36K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>40960</integer>
<key>description</key>
<string>40K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>45056</integer>
<key>description</key>
<string>44K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<integer>49152</integer>
<key>description</key>
<string>48K</string>
<key>default</key>
<true/>
</dict>
</array>
<key>media</key>
<dict>
<key>cass</key>
<integer>1</integer>
</dict>
<key>resolution</key>
<array>
<integer>560</integer>
<integer>384</integer>
<integer>192</integer>
</array>
<key>exp</key>
<key>slots</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>name</key>
<string>ramsize</string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
<string>RAM</string>
<key>options</key>
<array>
<dict>
<key>intValue</key>
<integer>4096</integer>
<key>description</key>
<string>4K</string>
<key>value</key>
<string>4K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>8192</integer>
<key>description</key>
<string>8K</string>
<key>value</key>
<string>8K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>12288</integer>
<key>description</key>
<string>12K</string>
<key>value</key>
<string>12K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>16384</integer>
<key>description</key>
<string>16K</string>
<key>value</key>
<string>16K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>20480</integer>
<key>description</key>
<string>20K</string>
<key>value</key>
<string>20K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>24576</integer>
<key>description</key>
<string>24K</string>
<key>value</key>
<string>24K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>28672</integer>
<key>description</key>
<string>28K</string>
<key>value</key>
<string>28K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>32768</integer>
<key>description</key>
<string>32K</string>
<key>value</key>
<string>32K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>36864</integer>
<key>description</key>
<string>36K</string>
<key>value</key>
<string>36K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>40960</integer>
<key>description</key>
<string>40K</string>
<key>value</key>
<string>40K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>45056</integer>
<key>description</key>
<string>44K</string>
<key>value</key>
<string>44K</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>intValue</key>
<integer>49152</integer>
<key>description</key>
<string>48K</string>
<key>value</key>
<string>48K</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>cassette</string>
<key>name</key>
<string>exp</string>
<key>description</key>
<string>Apple I cassette board</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>cass</key>
<integer>1</integer>
</dict>
<string>Expansion</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>cassette</string>
<key>description</key>
<string>Apple I Cassette Board</string>
<key>default</key>
<true/>
<key>devname</key>
<string>a1cass</string>
<key>media</key>
<dict>
<key>cass</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>cffa</string>
<key>description</key>
<string>CFFA Compact Flash For Apple I</string>
<key>devname</key>
<string>cffa1</string>
</dict>
</array>
</dict>
</array>
<key>devices</key>
<array>
<dict>
<key>value</key>
<string>cffa</string>
<key>description</key>
<string>CFFA Compact Flash for Apple I</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>hard</key>
<integer>1</integer>
</dict>
<key>name</key>
<string>cffa1</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:cffa_ata:0</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>cdrom</string>
<key>description</key>
<string>CD-ROM</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>cdrom</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>hdd</string>
<key>description</key>
<string>Hard Disk</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>hard</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>zip100</string>
<key>description</key>
<string>Iomega Zip 100MB IDE Drive</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>cr589</string>
<key>description</key>
<string>Matsushita CR589 CD-ROM Drive</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>xm3301</string>
<key>description</key>
<string>Toshiba XM-3301 CD-ROM Drive</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>:cffa_ata:1</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>cdrom</string>
<key>description</key>
<string>CD-ROM</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>cdrom</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>hdd</string>
<key>description</key>
<string>Hard Disk</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>hard</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>zip100</string>
<key>description</key>
<string>Iomega Zip 100MB IDE Drive</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>cr589</string>
<key>description</key>
<string>Matsushita CR589 CD-ROM Drive</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>xm3301</string>
<key>description</key>
<string>Toshiba XM-3301 CD-ROM Drive</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
</array>
<key>software</key>
<array>
<string>apple1.xml</string>
</array>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

View File

@ -6,241 +6,725 @@
<string>apple2c</string>
<key>description</key>
<string>Apple //c</string>
<key>ram</key>
<array>
<dict>
<key>value</key>
<integer>131072</integer>
<key>description</key>
<string>128K</string>
<key>default</key>
<true/>
</dict>
</array>
<key>media</key>
<dict>
</dict>
<key>resolution</key>
<array>
<integer>560</integer>
<integer>384</integer>
<integer>192</integer>
</array>
<key>gameio</key>
<key>slots</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>name</key>
<string>ramsize</string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
<string>RAM</string>
<key>options</key>
<array>
<dict>
<key>intValue</key>
<integer>131072</integer>
<key>description</key>
<string>128K</string>
<key>value</key>
<string>128K</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>joy</string>
<key>name</key>
<string>smartport</string>
<key>description</key>
<string>Apple II analog joysticks</string>
<key>default</key>
<false/>
<string>Disk Drives</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string></string>
<key>devname</key>
<string>smartport</string>
<key>default</key>
<true/>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>paddles</string>
<key>name</key>
<string>gameio</string>
<key>description</key>
<string>Apple II paddles</string>
<key>default</key>
<false/>
<string>Game I/O</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>joy</string>
<key>description</key>
<string>Apple II Analog Joysticks</string>
<key>devname</key>
<string>a2joy</string>
</dict>
<dict>
<key>value</key>
<string>paddles</string>
<key>description</key>
<string>Apple II Paddles</string>
<key>devname</key>
<string>a2pdls</string>
</dict>
<dict>
<key>value</key>
<string>compeyes</string>
<key>description</key>
<string>Digital Vision ComputerEyes</string>
<key>devname</key>
<string>a2ceyes</string>
<key>media</key>
<dict>
<key>picture</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>gizmo</string>
<key>description</key>
<string>HAL Labs Gizmo</string>
<key>devname</key>
<string>a2gizmo</string>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>compeyes</string>
<key>description</key>
<string>Digital Vision ComputerEyes</string>
<key>default</key>
<false/>
</dict>
</array>
<key>printer</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS232 Loopback</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS232 Loopback (DEC 12-15336-00)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS232 Null Modem</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<key>name</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>default</key>
<false/>
<string>Printer</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>devname</key>
<string>ie15_terminal</string>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>devname</key>
<string>scorpion_ic</string>
</dict>
<dict>
<key>value</key>
<string>nss_tvi</string>
<key>description</key>
<string>Novag Super System TV Interface</string>
<key>devname</key>
<string>nss_tvinterface</string>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>devname</key>
<string>pseudo_terminal</string>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>devname</key>
<string>rs_serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>devname</key>
<string>rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>devname</key>
<string>dec_rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>devname</key>
<string>null_modem</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>devname</key>
<string>rs232_patch_box</string>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>devname</key>
<string>rs232_sync_io</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>devname</key>
<string>serial_keyboard</string>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>devname</key>
<string>serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>devname</key>
<string>serial_terminal</string>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>devname</key>
<string>sunkbd_adaptor</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>devname</key>
<string>mockingboardd</string>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>devname</key>
<string>swtpc8212_terminal</string>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>name</key>
<string>modem</string>
<key>description</key>
<string>Serial Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>default</key>
<false/>
<string>Modem</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>devname</key>
<string>ie15_terminal</string>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>devname</key>
<string>scorpion_ic</string>
</dict>
<dict>
<key>value</key>
<string>nss_tvi</string>
<key>description</key>
<string>Novag Super System TV Interface</string>
<key>devname</key>
<string>nss_tvinterface</string>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>devname</key>
<string>pseudo_terminal</string>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>devname</key>
<string>rs_serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>devname</key>
<string>rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>devname</key>
<string>dec_rs232_loopback</string>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>devname</key>
<string>null_modem</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>devname</key>
<string>rs232_patch_box</string>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>devname</key>
<string>rs232_sync_io</string>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>devname</key>
<string>serial_keyboard</string>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>devname</key>
<string>serial_printer</string>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>devname</key>
<string>serial_terminal</string>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>devname</key>
<string>sunkbd_adaptor</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>devname</key>
<string>mockingboardd</string>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>devname</key>
<string>swtpc8212_terminal</string>
</dict>
</array>
</dict>
</array>
<key>modem</key>
<key>devices</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
<key>name</key>
<string>smartport</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>sl6:0</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>525</string>
<key>description</key>
<string>5.25"</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>floppy_5_25</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>sl6:1</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>525</string>
<key>description</key>
<string>5.25"</string>
<key>default</key>
<true/>
<key>media</key>
<dict>
<key>floppy_5_25</key>
<integer>1</integer>
</dict>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>default</key>
<false/>
<key>name</key>
<string>rs232_patch_box</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:dce</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>ie15</string>
<key>description</key>
<string>IE15 Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>scorpion</string>
<key>description</key>
<string>Micro-Robotics Scorpion Intelligent Controller</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>nss_tvi</string>
<key>description</key>
<string>Novag Super System TV Interface</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>rs_printer</string>
<key>description</key>
<string>Radio Shack Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS-232 Loopback</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS-232 Loopback (DEC 12-15336-00)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS-232 Null Modem</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>patch</string>
<key>description</key>
<string>RS-232 Patch Box</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>rs232_sync_io</string>
<key>description</key>
<string>RS-232 Synchronous I/O</string>
<key>default</key>
<false/>
<key>media</key>
<dict>
<key>bitbanger</key>
<integer>1</integer>
</dict>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard D</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>value</key>
<string>pty</string>
<key>description</key>
<string>Pseudo terminal</string>
<key>default</key>
<false/>
<key>name</key>
<string>sunkbd_adaptor</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:keyboard</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>type3hle</string>
<key>description</key>
<string>Sun Type 3 Keyboard (HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type4hle</string>
<key>description</key>
<string>Sun Type 4 Keyboard (HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5gbhle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Great Britain - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5jphle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Japan - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5sehle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (Sweden - HLE)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>type5hle</string>
<key>description</key>
<string>Sun Type 5 Keyboard (U.S.A. - HLE)</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
</array>
<key>software</key>
<array>
<string>apple2_flop_clcracked.xml</string>
<dict>
<key>value</key>
<string>loopback</string>
<key>description</key>
<string>RS232 Loopback</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>dec_loopback</string>
<key>description</key>
<string>RS232 Loopback (DEC 12-15336-00)</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>null_modem</string>
<key>description</key>
<string>RS232 Null Modem</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>keyboard</string>
<key>description</key>
<string>Serial Keyboard</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>printer</string>
<key>description</key>
<string>Serial Printer</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>terminal</string>
<key>description</key>
<string>Serial Terminal</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>sunkbd</string>
<key>description</key>
<string>Sun Keyboard Adaptor</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>swtpc8212</string>
<key>description</key>
<string>SWTPC8212 Terminal</string>
<key>default</key>
<false/>
<key>name</key>
<string>apple2_flop_orig.xml</string>
<key>filter</key>
<string>A2C</string>
</dict>
<string>apple2_flop_misc.xml</string>
</array>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More