Compare commits

...

34 Commits
v2.5 ... master

Author SHA1 Message Date
Jesús A. Álvarez fdbf6aab7e iPad: when creating a new window, take over and close the previous one 2024-03-04 23:54:25 +01:00
Jesús A. Álvarez 19c0072d4c fix quick actions 2024-03-04 23:39:41 +01:00
Jesús A. Álvarez da3f639ef2 prefer pixel-perfect scaling when filter is set to nearest 2024-03-02 11:51:29 +01:00
Jesús A. Álvarez 65d377884b auto-hide home indicator 2024-03-01 22:49:04 +01:00
Jesús A. Álvarez 2dab9cca28 update README 2024-03-01 22:24:34 +01:00
Jesús A. Álvarez fcb71f79ff visionOS: use native toggles in menus 2024-02-17 15:21:41 +01:00
Jesús A. Álvarez 2ccef4e3a6 visionOS: add “run in background” setting and respect it 2024-02-17 15:21:41 +01:00
Jesús A. Álvarez fca6943bfe close keyboard when closing screen 2024-02-17 14:42:31 +01:00
Jesús A. Álvarez afef4e5b25 always show keyboard again when pressing keyboard button 2024-02-17 14:41:22 +01:00
Jesús A. Álvarez 772ce2c326 handle mouse input with UIHoverGestureRecognizer 2024-02-17 14:35:19 +01:00
Jesús A. Álvarez ef6ef61037 target iOS 13.4 2024-02-17 13:31:39 +01:00
Jesús A. Álvarez 3b4244e4e3 ifdef around all visionOS-specific things 2024-02-17 13:25:32 +01:00
Jesús A. Álvarez c1c7c93c6a handle key input with UIPress (iOS ≥9)
contributed by Steven Troughton-Smith
2024-02-17 13:25:32 +01:00
Jesús A. Álvarez 61dc6ddcd7 target iOS 13.0 2024-02-17 13:20:50 +01:00
Jesús A. Álvarez 0204043e10 add glass background to bar, remove from buttons 2024-02-16 21:29:22 +01:00
Jesús A. Álvarez 043c20b645 visionOS: make keyboard resizable ±25% 2024-02-10 21:37:13 +01:00
Jesús A. Álvarez 7a93412c3f visionOS: add reset, interrupt and shut down controls 2024-02-10 14:52:06 +01:00
Jesús A. Álvarez e1adde78f0 visionOS: hide toolbar from insert disk modal 2024-02-10 14:43:09 +01:00
Jesús A. Álvarez 632f01f169 visionOS: native settings menu 2024-02-10 14:43:09 +01:00
Jesús A. Álvarez ed99d1bbfb visionOS: show layout menu from keyboard button 2024-02-10 14:23:42 +01:00
Jesús A. Álvarez 53cb92f4ef find keyboard layouts from AppDelegate 2024-02-10 14:09:02 +01:00
Jesús A. Álvarez 22256824d2 make AppDelegate a bit swifty 2024-02-10 13:36:20 +01:00
Jesús A. Álvarez 3b96faf502 fix bundle identifier for MacII-512x384 2024-02-10 13:31:28 +01:00
Jesús A. Álvarez 33e01e0847 visionOS: always use touchscreen 2024-02-10 12:19:20 +01:00
Jesús A. Álvarez 7c1f280374 keyboard for visionOS 2024-02-10 12:15:01 +01:00
Jesús A. Álvarez 4aef44bf76 add icon for visionOS 2024-02-10 12:02:13 +01:00
Jesús A. Álvarez cf86226c6b build for visionOS 2024-02-09 16:06:37 +01:00
Jesús A. Álvarez 8f4bc46d12 target iOS 12.0 2024-02-09 15:39:32 +01:00
Jesús A. Álvarez 003c075108 update readme 2023-09-27 20:37:16 +02:00
Jesús A. Álvarez e2707af5ce use release build by default 2023-09-27 19:42:58 +02:00
Jesús A. Álvarez e8c8b8375f add 512×384 variant of Mac II 2023-09-27 19:42:36 +02:00
Jesús A. Álvarez 3db3bb6091 fix build with Xcode 15 2023-09-27 19:29:43 +02:00
Jesús A. Álvarez 7e2fc6ef59 update copyright year, change twitter link to mastodon 2023-02-03 21:48:24 +01:00
Jesús A. Álvarez ceb0813eee steal key events if handled by emulator
fixes #45 somewhat, but not for ⌘-Q or ⌘-H
2023-02-01 18:11:49 +01:00
81 changed files with 1941 additions and 347 deletions

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@ -30,12 +30,38 @@
28BA89801CE7315400A98104 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BA89791CE7315400A98104 /* KBKeyboardView.m */; };
28BA89821CE7336500A98104 /* Keyboard Layouts in Resources */ = {isa = PBXBuildFile; fileRef = 28BA89811CE7336500A98104 /* Keyboard Layouts */; };
28BA89851CE73E7200A98104 /* TrackPad.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BA89841CE73E7200A98104 /* TrackPad.m */; };
28BA89881CE73FBC00A98104 /* MNVMApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BA89871CE73FBC00A98104 /* MNVMApplication.m */; };
28BDBEA01D230EEB0072ED5B /* MYOSGLUE.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */; };
28BDBEB11D230EEB0072ED5B /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423EC1CFA329C0088B634 /* Icon.png */; };
28BDBEB21D230EEB0072ED5B /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423ED1CFA329C0088B634 /* Icon@2x.png */; };
28BDBEB31D230EEB0072ED5B /* Icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423EE1CFA329C0088B634 /* Icon@3x.png */; };
28C67BD22AC49E46000C7540 /* SCSIEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D9251D0F13007C273F /* SCSIEMDV.c */; };
28C67BD32AC49E46000C7540 /* MINEM68K.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D3251D0F13007C273F /* MINEM68K.c */; };
28C67BD42AC49E46000C7540 /* GLOBGLUE.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7CE251D0F12007C273F /* GLOBGLUE.c */; };
28C67BD52AC49E46000C7540 /* M68KITAB.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7CF251D0F12007C273F /* M68KITAB.c */; };
28C67BD62AC49E46000C7540 /* PROGMAIN.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D0251D0F12007C273F /* PROGMAIN.c */; };
28C67BD72AC49E46000C7540 /* ADBEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D2251D0F13007C273F /* ADBEMDEV.c */; };
28C67BD82AC49E46000C7540 /* VIA2EMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D6251D0F13007C273F /* VIA2EMDV.c */; };
28C67BD92AC49E46000C7540 /* IWMEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D5251D0F13007C273F /* IWMEMDEV.c */; };
28C67BDA2AC49E46000C7540 /* VIAEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7DC251D0F13007C273F /* VIAEMDEV.c */; };
28C67BDB2AC49E46000C7540 /* SCRNEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D4251D0F13007C273F /* SCRNEMDV.c */; };
28C67BDC2AC49E46000C7540 /* SONYEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D1251D0F12007C273F /* SONYEMDV.c */; };
28C67BDD2AC49E46000C7540 /* ROMEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7DA251D0F13007C273F /* ROMEMDEV.c */; };
28C67BDE2AC49E46000C7540 /* MYOSGLUE.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */; };
28C67BDF2AC49E46000C7540 /* RTCEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7CD251D0F12007C273F /* RTCEMDEV.c */; };
28C67BE02AC49E46000C7540 /* SCCEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D7251D0F13007C273F /* SCCEMDEV.c */; };
28C67BE12AC49E46000C7540 /* MOUSEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7CC251D0F12007C273F /* MOUSEMDV.c */; };
28C67BE22AC49E46000C7540 /* VIDEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7D8251D0F13007C273F /* VIDEMDEV.c */; };
28C67BE32AC49E46000C7540 /* ASCEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7DE251D0F13007C273F /* ASCEMDEV.c */; };
28C67BE72AC49E46000C7540 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423EC1CFA329C0088B634 /* Icon.png */; };
28C67BE82AC49E46000C7540 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423ED1CFA329C0088B634 /* Icon@2x.png */; };
28C67BE92AC49E46000C7540 /* Icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423EE1CFA329C0088B634 /* Icon@3x.png */; };
28C67BF62AC49FA1000C7540 /* MacII-512x384.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 28C67BEE2AC49E46000C7540 /* MacII-512x384.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
28CE8ED61CD4F56C00FE25A8 /* ScreenView.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */; };
28D3C6152B7681420079E915 /* VisionSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C6142B7681420079E915 /* VisionSupport.swift */; };
28D3C6172B76B8970079E915 /* DefaultSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C6162B76B8970079E915 /* DefaultSceneDelegate.swift */; };
28D3C61B2B7781700079E915 /* KeyboardSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C61A2B7781700079E915 /* KeyboardSceneDelegate.swift */; };
28D3C61D2B7795060079E915 /* SettingsMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C61C2B7795060079E915 /* SettingsMenu.swift */; };
28D3C61F2B77B51D0079E915 /* PowerMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C61E2B77B51D0079E915 /* PowerMenu.swift */; };
28D5A3FD1CD6868F001A33F6 /* TouchScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D5A3FC1CD6868E001A33F6 /* TouchScreen.m */; };
28E3B7DF251D0F13007C273F /* MOUSEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7CC251D0F12007C273F /* MOUSEMDV.c */; };
28E3B7E0251D0F13007C273F /* MOUSEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7CC251D0F12007C273F /* MOUSEMDV.c */; };
@ -148,6 +174,13 @@
remoteGlobalIDString = 2834237D1CF9C4CB0088B634;
remoteInfo = MacII;
};
2872E19D2AC48D770014F276 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 28F676B51CD15E0B00FC6FA6 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 28BDBE9A1D230EEB0072ED5B;
remoteInfo = "MacII-640x480";
};
289710E01CFB126D0089D463 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 28F676B51CD15E0B00FC6FA6 /* Project object */;
@ -155,6 +188,13 @@
remoteGlobalIDString = 289710B81CFB11BF0089D463;
remoteInfo = Mac128K;
};
28C67BF42AC49F8D000C7540 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 28F676B51CD15E0B00FC6FA6 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 28C67BD02AC49E46000C7540;
remoteInfo = "MacII-512x384";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@ -164,6 +204,7 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
28C67BF62AC49FA1000C7540 /* MacII-512x384.framework in Embed Frameworks */,
281BB6C91D231F7700BF87B0 /* MacII-640x480.framework in Embed Frameworks */,
289710DF1CFB12660089D463 /* Mac128K.framework in Embed Frameworks */,
283423A31CF9C5880088B634 /* MacII.framework in Embed Frameworks */,
@ -235,12 +276,20 @@
28BA89811CE7336500A98104 /* Keyboard Layouts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "Keyboard Layouts"; sourceTree = "<group>"; };
28BA89831CE73E7200A98104 /* TrackPad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPad.h; sourceTree = "<group>"; };
28BA89841CE73E7200A98104 /* TrackPad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TrackPad.m; sourceTree = "<group>"; };
28BA89861CE73FBC00A98104 /* MNVMApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MNVMApplication.h; sourceTree = "<group>"; };
28BA89871CE73FBC00A98104 /* MNVMApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MNVMApplication.m; sourceTree = "<group>"; };
28BDBEB71D230EEB0072ED5B /* MacII-640x480.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "MacII-640x480.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
28C67BEE2AC49E46000C7540 /* MacII-512x384.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "MacII-512x384.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
28C67BF12AC49F0F000C7540 /* CNFUDALL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNFUDALL.h; sourceTree = "<group>"; };
28C67BF22AC49F0F000C7540 /* CNFUDPIC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNFUDPIC.h; sourceTree = "<group>"; };
28C67BF32AC49F0F000C7540 /* CNFUDOSG.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNFUDOSG.h; sourceTree = "<group>"; };
28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYOSGLUE.m; sourceTree = "<group>"; };
28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenView.h; sourceTree = "<group>"; };
28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScreenView.m; sourceTree = "<group>"; };
28D3C6132B7681420079E915 /* Mini vMac-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Mini vMac-Bridging-Header.h"; sourceTree = "<group>"; };
28D3C6142B7681420079E915 /* VisionSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisionSupport.swift; sourceTree = "<group>"; };
28D3C6162B76B8970079E915 /* DefaultSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultSceneDelegate.swift; sourceTree = "<group>"; };
28D3C61A2B7781700079E915 /* KeyboardSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardSceneDelegate.swift; sourceTree = "<group>"; };
28D3C61C2B7795060079E915 /* SettingsMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsMenu.swift; sourceTree = "<group>"; };
28D3C61E2B77B51D0079E915 /* PowerMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerMenu.swift; sourceTree = "<group>"; };
28D5A3FB1CD6868E001A33F6 /* TouchScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TouchScreen.h; sourceTree = "<group>"; };
28D5A3FC1CD6868E001A33F6 /* TouchScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TouchScreen.m; sourceTree = "<group>"; };
28E3B7CC251D0F12007C273F /* MOUSEMDV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MOUSEMDV.c; sourceTree = "<group>"; };
@ -360,6 +409,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
28C67BE42AC49E46000C7540 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
28F676BA1CD15E0B00FC6FA6 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -413,6 +469,7 @@
283422F01CF8F3530088B634 /* Shared */,
283422CB1CF8EF8C0088B634 /* MacPlus4M */,
283423981CF9C5380088B634 /* MacII */,
28C67BF02AC49F0F000C7540 /* MacII-512x384 */,
28BDBEB91D230F280072ED5B /* MacII-640x480 */,
289710D51CFB11D90089D463 /* Mac128K */,
);
@ -485,6 +542,16 @@
path = "MacII-640x480";
sourceTree = "<group>";
};
28C67BF02AC49F0F000C7540 /* MacII-512x384 */ = {
isa = PBXGroup;
children = (
28C67BF12AC49F0F000C7540 /* CNFUDALL.h */,
28C67BF22AC49F0F000C7540 /* CNFUDPIC.h */,
28C67BF32AC49F0F000C7540 /* CNFUDOSG.h */,
);
path = "MacII-512x384";
sourceTree = "<group>";
};
28E3B7CB251D0EEC007C273F /* src */ = {
isa = PBXGroup;
children = (
@ -532,6 +599,7 @@
283423961CF9C4CB0088B634 /* MacII.framework */,
289710D41CFB11BF0089D463 /* Mac128K.framework */,
28BDBEB71D230EEB0072ED5B /* MacII-640x480.framework */,
28C67BEE2AC49E46000C7540 /* MacII-512x384.framework */,
);
name = Products;
sourceTree = "<group>";
@ -541,8 +609,6 @@
children = (
28F676C31CD15E0B00FC6FA6 /* AppDelegate.h */,
28F676C41CD15E0B00FC6FA6 /* AppDelegate.m */,
28BA89861CE73FBC00A98104 /* MNVMApplication.h */,
28BA89871CE73FBC00A98104 /* MNVMApplication.m */,
28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */,
28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */,
28D5A3FB1CD6868E001A33F6 /* TouchScreen.h */,
@ -551,6 +617,9 @@
28BA89841CE73E7200A98104 /* TrackPad.m */,
28F676C61CD15E0B00FC6FA6 /* ViewController.h */,
28F676C71CD15E0B00FC6FA6 /* ViewController.m */,
28D3C6142B7681420079E915 /* VisionSupport.swift */,
28D3C61C2B7795060079E915 /* SettingsMenu.swift */,
28D3C61E2B77B51D0079E915 /* PowerMenu.swift */,
28848B601CDE97D600B86C45 /* InsertDiskViewController.h */,
28848B611CDE97D600B86C45 /* InsertDiskViewController.m */,
28848B631CDE97E900B86C45 /* SettingsViewController.h */,
@ -567,6 +636,8 @@
28F6B4CE1CF77099002D76D0 /* compat.m */,
283CA9821DF47AF300B33D5E /* BTCMouse.h */,
283422EF1CF8F33A0088B634 /* Emulator Bundles */,
28D3C6162B76B8970079E915 /* DefaultSceneDelegate.swift */,
28D3C61A2B7781700079E915 /* KeyboardSceneDelegate.swift */,
);
path = "Mini vMac";
sourceTree = "<group>";
@ -574,6 +645,7 @@
28F676C01CD15E0B00FC6FA6 /* Supporting Files */ = {
isa = PBXGroup;
children = (
28D3C6132B7681420079E915 /* Mini vMac-Bridging-Header.h */,
28F6B4551CF07C9A002D76D0 /* libhfs */,
28F6B4541CF07C8D002D76D0 /* libmfs */,
28F6B4531CF07C83002D76D0 /* libres */,
@ -684,6 +756,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
28C67BE52AC49E46000C7540 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
@ -763,6 +842,25 @@
productReference = 28BDBEB71D230EEB0072ED5B /* MacII-640x480.framework */;
productType = "com.apple.product-type.framework";
};
28C67BD02AC49E46000C7540 /* MacII-512x384 */ = {
isa = PBXNativeTarget;
buildConfigurationList = 28C67BEB2AC49E46000C7540 /* Build configuration list for PBXNativeTarget "MacII-512x384" */;
buildPhases = (
28C67BD12AC49E46000C7540 /* Sources */,
28C67BE42AC49E46000C7540 /* Frameworks */,
28C67BE52AC49E46000C7540 /* Headers */,
28C67BE62AC49E46000C7540 /* Resources */,
28C67BEA2AC49E46000C7540 /* Add capabilities to Info.plist */,
);
buildRules = (
);
dependencies = (
);
name = "MacII-512x384";
productName = "minivmac-plus4m";
productReference = 28C67BEE2AC49E46000C7540 /* MacII-512x384.framework */;
productType = "com.apple.product-type.framework";
};
28F676BC1CD15E0B00FC6FA6 /* Mini vMac */ = {
isa = PBXNativeTarget;
buildConfigurationList = 28F676D41CD15E0B00FC6FA6 /* Build configuration list for PBXNativeTarget "Mini vMac" */;
@ -770,13 +868,15 @@
28F676B91CD15E0B00FC6FA6 /* Sources */,
28F676BA1CD15E0B00FC6FA6 /* Frameworks */,
28F676BB1CD15E0B00FC6FA6 /* Resources */,
28F6B4CD1CF76D88002D76D0 /* Set Git version in Info.plist */,
283422D61CF8EF8C0088B634 /* Embed Frameworks */,
283422F51CF9ACAD0088B634 /* Change emulator bundle extensions to mnvm */,
28F6B4CD1CF76D88002D76D0 /* Set Git version in Info.plist */,
);
buildRules = (
);
dependencies = (
28C67BF52AC49F8D000C7540 /* PBXTargetDependency */,
2872E19E2AC48D770014F276 /* PBXTargetDependency */,
289710E11CFB126D0089D463 /* PBXTargetDependency */,
283422D01CF8EF8C0088B634 /* PBXTargetDependency */,
283423A11CF9C5730088B634 /* PBXTargetDependency */,
@ -862,6 +962,7 @@
28F676BC1CD15E0B00FC6FA6 = {
CreatedOnToolsVersion = 7.3;
DevelopmentTeam = UJXNDZ5TNU;
LastSwiftMigration = 1520;
};
28F6B48D1CF07DDD002D76D0 = {
CreatedOnToolsVersion = 7.3.1;
@ -895,6 +996,7 @@
2834237D1CF9C4CB0088B634 /* MacII */,
289710B81CFB11BF0089D463 /* Mac128K */,
28BDBE9A1D230EEB0072ED5B /* MacII-640x480 */,
28C67BD02AC49E46000C7540 /* MacII-512x384 */,
);
};
/* End PBXProject section */
@ -940,6 +1042,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
28C67BE62AC49E46000C7540 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
28C67BE72AC49E46000C7540 /* Icon.png in Resources */,
28C67BE82AC49E46000C7540 /* Icon@2x.png in Resources */,
28C67BE92AC49E46000C7540 /* Icon@3x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
28F676BB1CD15E0B00FC6FA6 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -957,6 +1069,7 @@
/* Begin PBXShellScriptBuildPhase section */
283422F51CF9ACAD0088B634 /* Change emulator bundle extensions to mnvm */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -969,23 +1082,39 @@
shellPath = /bin/sh;
shellScript = "cd \"$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH\"\nrm -rf *.mnvm\nfor name in *.framework\ndo\n mv \"$name\" \"${name%.framework}.mnvm\"\ndone\n";
};
28F6B4CD1CF76D88002D76D0 /* Set Git version in Info.plist */ = {
28C67BEA2AC49E46000C7540 /* Add capabilities to Info.plist */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Info.plist,
);
name = "Add capabilities to Info.plist";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "PlistBuddy=/usr/libexec/PlistBuddy\ncc \"-D$INFOPLIST_PREPROCESSOR_DEFINITIONS\" -P -E -x c -include \"$INFOPLIST_PREFIX_HEADER\" \"$SRCROOT/Mini vMac/PlugIn-Capabilities.plist.xml\" -o \"$TARGET_TEMP_DIR/Capabilities.plist\"\n$PlistBuddy -c \"Merge '$TARGET_TEMP_DIR/Capabilities.plist'\" \"$TARGET_BUILD_DIR/$INFOPLIST_PATH\"\n";
};
28F6B4CD1CF76D88002D76D0 /* Set Git version in Info.plist */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 12;
files = (
);
inputPaths = (
);
name = "Set Git version in Info.plist";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "GIT=`which git`\nif [ \"$GIT\" -a -d .git ]; then\nGIT_VERSION=`$GIT describe --tags --always`\nelse\nGIT_VERSION=unknown\nfi\ndefaults write \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Info\" GitVersion -string $GIT_VERSION\nchmod 0644 \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Info.plist\"\n";
shellScript = "GIT=`which git`\nif [ \"$GIT\" -a -d .git ]; then\nGIT_VERSION=`$GIT describe --tags --always`\nelse\nGIT_VERSION=unknown\nfi\ndefaults write \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Info\" GitVersion -string \"$GIT_VERSION\"\nchmod 0644 \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Info.plist\"\n";
};
28F8758E1D2936B5001E99EB /* Add capabilities to Info.plist */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -1000,6 +1129,7 @@
};
28F8758F1D293FF4001E99EB /* Add capabilities to Info.plist */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -1014,6 +1144,7 @@
};
28F875901D293FFB001E99EB /* Add capabilities to Info.plist */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -1028,6 +1159,7 @@
};
28F875911D294001001E99EB /* Add capabilities to Info.plist */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -1139,18 +1271,47 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
28C67BD12AC49E46000C7540 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
28C67BD22AC49E46000C7540 /* SCSIEMDV.c in Sources */,
28C67BD32AC49E46000C7540 /* MINEM68K.c in Sources */,
28C67BD42AC49E46000C7540 /* GLOBGLUE.c in Sources */,
28C67BD52AC49E46000C7540 /* M68KITAB.c in Sources */,
28C67BD62AC49E46000C7540 /* PROGMAIN.c in Sources */,
28C67BD72AC49E46000C7540 /* ADBEMDEV.c in Sources */,
28C67BD82AC49E46000C7540 /* VIA2EMDV.c in Sources */,
28C67BD92AC49E46000C7540 /* IWMEMDEV.c in Sources */,
28C67BDA2AC49E46000C7540 /* VIAEMDEV.c in Sources */,
28C67BDB2AC49E46000C7540 /* SCRNEMDV.c in Sources */,
28C67BDC2AC49E46000C7540 /* SONYEMDV.c in Sources */,
28C67BDD2AC49E46000C7540 /* ROMEMDEV.c in Sources */,
28C67BDE2AC49E46000C7540 /* MYOSGLUE.m in Sources */,
28C67BDF2AC49E46000C7540 /* RTCEMDEV.c in Sources */,
28C67BE02AC49E46000C7540 /* SCCEMDEV.c in Sources */,
28C67BE12AC49E46000C7540 /* MOUSEMDV.c in Sources */,
28C67BE22AC49E46000C7540 /* VIDEMDEV.c in Sources */,
28C67BE32AC49E46000C7540 /* ASCEMDEV.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
28F676B91CD15E0B00FC6FA6 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
28D3C6152B7681420079E915 /* VisionSupport.swift in Sources */,
28BA897E1CE7315400A98104 /* KBKey.m in Sources */,
28BA89851CE73E7200A98104 /* TrackPad.m in Sources */,
28D3C6172B76B8970079E915 /* DefaultSceneDelegate.swift in Sources */,
28CE8ED61CD4F56C00FE25A8 /* ScreenView.m in Sources */,
28848B651CDE97E900B86C45 /* SettingsViewController.m in Sources */,
28BA89881CE73FBC00A98104 /* MNVMApplication.m in Sources */,
28F6B4CF1CF77099002D76D0 /* compat.m in Sources */,
28F6B4521CF07C48002D76D0 /* UIImage+DiskImageIcon.m in Sources */,
28D3C61D2B7795060079E915 /* SettingsMenu.swift in Sources */,
28BA897F1CE7315400A98104 /* KBKeyboardLayout.m in Sources */,
28D3C61B2B7781700079E915 /* KeyboardSceneDelegate.swift in Sources */,
28D3C61F2B77B51D0079E915 /* PowerMenu.swift in Sources */,
28848B621CDE97D600B86C45 /* InsertDiskViewController.m in Sources */,
28F676C81CD15E0B00FC6FA6 /* ViewController.m in Sources */,
28D5A3FD1CD6868F001A33F6 /* TouchScreen.m in Sources */,
@ -1209,11 +1370,21 @@
target = 2834237D1CF9C4CB0088B634 /* MacII */;
targetProxy = 283423A01CF9C5730088B634 /* PBXContainerItemProxy */;
};
2872E19E2AC48D770014F276 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 28BDBE9A1D230EEB0072ED5B /* MacII-640x480 */;
targetProxy = 2872E19D2AC48D770014F276 /* PBXContainerItemProxy */;
};
289710E11CFB126D0089D463 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 289710B81CFB11BF0089D463 /* Mac128K */;
targetProxy = 289710E01CFB126D0089D463 /* PBXContainerItemProxy */;
};
28C67BF52AC49F8D000C7540 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 28C67BD02AC49E46000C7540 /* MacII-512x384 */;
targetProxy = 28C67BF42AC49F8D000C7540 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@ -1251,12 +1422,25 @@
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.macplus4m;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\" \"$(SRCROOT)/Mini vMac/\" \"$(SRCROOT)/minivmac/src\"";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -1278,12 +1462,25 @@
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.macplus4m;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\" \"$(SRCROOT)/Mini vMac/\" \"$(SRCROOT)/minivmac/src\"";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -1305,12 +1502,25 @@
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.macii;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\" \"$(SRCROOT)/Mini vMac/\" \"$(SRCROOT)/minivmac/src\"";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -1332,12 +1542,25 @@
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.macii;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\" \"$(SRCROOT)/Mini vMac/\" \"$(SRCROOT)/minivmac/src\"";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -1359,12 +1582,25 @@
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.mac128k;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\" \"$(SRCROOT)/Mini vMac/\" \"$(SRCROOT)/minivmac/src\"";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -1386,12 +1622,25 @@
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.mac128k;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\" \"$(SRCROOT)/Mini vMac/\" \"$(SRCROOT)/minivmac/src\"";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -1413,12 +1662,25 @@
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-640x480";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\" \"$(SRCROOT)/Mini vMac/\" \"$(SRCROOT)/minivmac/src\"";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -1440,12 +1702,105 @@
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-640x480";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\" \"$(SRCROOT)/Mini vMac/\" \"$(SRCROOT)/minivmac/src\"";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
28C67BEC2AC49E46000C7540 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = NO;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "$(SRCROOT)/Mini vMac/PlugIn-Info.plist";
INFOPLIST_PREFIX_HEADER = "$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)/CNFUDALL.h";
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-512x384";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
28C67BED2AC49E46000C7540 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = NO;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "$(SRCROOT)/Mini vMac/PlugIn-Info.plist";
INFOPLIST_PREFIX_HEADER = "$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)/CNFUDALL.h";
INFOPLIST_PREPROCESS = YES;
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-512x384";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,7";
USER_HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
"\"$(SRCROOT)/Mini vMac/\"",
"\"$(SRCROOT)/minivmac/src\"",
);
USE_HEADERMAP = NO;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -1504,6 +1859,7 @@
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@ -1553,6 +1909,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@ -1562,19 +1919,30 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 14;
DEVELOPMENT_TEAM = UJXNDZ5TNU;
HEADER_SEARCH_PATHS = "$(SRCROOT)";
INFOPLIST_FILE = "Mini vMac/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.5;
OTHER_CFLAGS = "-DUSE_LIBRES";
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Mini vMac/Mini vMac-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,7";
};
name = Debug;
};
@ -1582,83 +1950,117 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 14;
DEVELOPMENT_TEAM = UJXNDZ5TNU;
HEADER_SEARCH_PATHS = "$(SRCROOT)";
INFOPLIST_FILE = "Mini vMac/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.5;
OTHER_CFLAGS = "-DUSE_LIBRES";
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Mini vMac/Mini vMac-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,7";
};
name = Release;
};
28F6B4951CF07DDD002D76D0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
CLANG_ENABLE_MODULES = NO;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
OTHER_CFLAGS = "-DHAVE_CONFIG_H";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
SUPPORTS_MACCATALYST = YES;
};
name = Debug;
};
28F6B4961CF07DDD002D76D0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
CLANG_ENABLE_MODULES = NO;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
OTHER_CFLAGS = "-DHAVE_CONFIG_H";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
SUPPORTS_MACCATALYST = YES;
};
name = Release;
};
28F6B4AF1CF07EC9002D76D0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = NO;
HEADER_SEARCH_PATHS = "$(SRCROOT)";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
OTHER_CFLAGS = "-DUSE_LIBRES";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
SUPPORTS_MACCATALYST = YES;
};
name = Debug;
};
28F6B4B01CF07EC9002D76D0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = NO;
HEADER_SEARCH_PATHS = "$(SRCROOT)";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
OTHER_CFLAGS = "-DUSE_LIBRES";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
SUPPORTS_MACCATALYST = YES;
};
name = Release;
};
28F6B4BD1CF07F32002D76D0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
SUPPORTS_MACCATALYST = YES;
};
name = Debug;
};
28F6B4BE1CF07F32002D76D0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
SUPPORTS_MACCATALYST = YES;
};
name = Release;
};
@ -1701,6 +2103,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
28C67BEB2AC49E46000C7540 /* Build configuration list for PBXNativeTarget "MacII-512x384" */ = {
isa = XCConfigurationList;
buildConfigurations = (
28C67BEC2AC49E46000C7540 /* Debug */,
28C67BED2AC49E46000C7540 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
28F676B81CD15E0B00FC6FA6 /* Build configuration list for PBXProject "Mini vMac" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Mini vMac.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,37 @@
{
"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "9C19786155D97B8ED78AB84AFAAA50249126341A",
"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
},
"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
"9C19786155D97B8ED78AB84AFAAA50249126341A" : 0,
"F2E8D120DACD6BF5E1EFFA012C92CE6FA0E44B4C" : 0,
"45D35ABA2A883CFEB6F6014CF9723CDA568B602B" : 0
},
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "A273011D-9F4F-4F93-8287-77CF2E175709",
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
"9C19786155D97B8ED78AB84AFAAA50249126341A" : "minivmac4ios\/",
"F2E8D120DACD6BF5E1EFFA012C92CE6FA0E44B4C" : "minivmac4ios\/libres\/",
"45D35ABA2A883CFEB6F6014CF9723CDA568B602B" : "minivmac4ios\/libmfs\/"
},
"DVTSourceControlWorkspaceBlueprintNameKey" : "Mini vMac",
"DVTSourceControlWorkspaceBlueprintVersion" : 204,
"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Mini vMac.xcodeproj",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
{
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/zydeco\/libmfs.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "45D35ABA2A883CFEB6F6014CF9723CDA568B602B"
},
{
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:zydeco\/minivmac4ios.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "9C19786155D97B8ED78AB84AFAAA50249126341A"
},
{
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/zydeco\/libres.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "F2E8D120DACD6BF5E1EFFA012C92CE6FA0E44B4C"
}
]
}

View File

@ -31,7 +31,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1500"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "28C67BD02AC49E46000C7540"
BuildableName = "MacII-512x384.framework"
BlueprintName = "MacII-512x384"
ReferencedContainer = "container:Mini vMac.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "28C67BD02AC49E46000C7540"
BuildableName = "MacII-512x384.framework"
BlueprintName = "MacII-512x384"
ReferencedContainer = "container:Mini vMac.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -31,7 +31,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"

View File

@ -31,7 +31,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"

View File

@ -31,7 +31,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"

View File

@ -22,15 +22,17 @@ extern NSString *DocumentsChangedNotification;
@property (nonatomic, readonly) NSString *emulatorBundlesPath;
@property (readonly, nonatomic, getter = isSandboxed) BOOL sandboxed;
@property (readonly, nonatomic) id<Emulator> sharedEmulator;
@property (readonly, nonatomic) NSArray<NSString*> *keyboardLayoutPaths;
+ (instancetype)sharedInstance;
+ (id<Emulator>)sharedEmulator;
@property (class, readonly, strong) AppDelegate *sharedInstance NS_SWIFT_NAME(shared);
@property (class, readonly, strong) id<Emulator> sharedEmulator NS_SWIFT_NAME(emulator);
- (void)loadAndStartEmulator;
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message;
- (IBAction)showInsertDisk:(id)sender;
- (IBAction)showSettings:(id)sender;
- (IBAction)showGestureHelp:(id)sender;
- (UIScene*)sceneWithName:(NSString*)name;
@end

View File

@ -10,6 +10,7 @@
#import "AppDelegate.h"
#import "SettingsViewController.h"
#import "InsertDiskViewController.h"
#import "ViewController.h"
static AppDelegate *sharedAppDelegate = nil;
static NSObject<Emulator> *sharedEmulator = nil;
@ -101,7 +102,14 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
NSBundle *emulatorBundle = [NSBundle bundleWithPath:emulatorBundlePath];
[emulatorBundle load];
sharedEmulator = [[emulatorBundle principalClass] new];
sharedEmulator.rootViewController = self.window.rootViewController;
sharedEmulator.showAlert = ^(NSString *title, NSString *message) {
[self showAlertWithTitle:title message:message];
};
sharedEmulator.dataPath = self.documentsPath;
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
[ViewController adjustToScreenSize];
#endif
return sharedEmulator != nil;
}
@ -167,8 +175,11 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
});
return;
}
BOOL wasRunning = sharedEmulator.isRunning;
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[sharedEmulator setRunning:wasRunning];
}]];
UIViewController *controller = self.window.rootViewController;
while (controller.presentedViewController) {
controller = controller.presentedViewController;
@ -178,7 +189,7 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
BOOL success = NO;
if ([shortcutItem.type isEqualToString:@"disk"] && sharedEmulator.isRunning) {
if ([shortcutItem.type isEqualToString:@"disk"]) {
NSString *fileName = (NSString*)shortcutItem.userInfo[@"disk"];
NSString *filePath = [self.documentsPath stringByAppendingPathComponent:fileName];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath] && ![sharedEmulator isDiskInserted:filePath]) {
@ -246,6 +257,16 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
return userKeyboardLayoutsPath;
}
- (NSArray<NSString *> *)keyboardLayoutPaths {
NSArray *keyboardLayouts = [[NSBundle mainBundle] pathsForResourcesOfType:@"nfkeyboardlayout" inDirectory:@"Keyboard Layouts"];
NSString *userKeyboardLayoutsPath = [AppDelegate sharedInstance].userKeyboardLayoutsPath;
NSArray *userKeyboardLayouts = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:userKeyboardLayoutsPath error:nil] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"pathExtension.lowercaseString = %@", @"nfkeyboardlayout"]];
if (userKeyboardLayouts.count > 0) {
keyboardLayouts = [keyboardLayouts arrayByAddingObjectsFromArray:userKeyboardLayouts];
}
return keyboardLayouts;
}
- (BOOL)importFileToDocuments:(NSURL *)url copy:(BOOL)copy {
if (url.fileURL) {
// opening file
@ -304,4 +325,41 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
return YES;
}
#pragma mark - Making a Scene
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
for (NSUserActivity *activity in options.userActivities) {
if ([activity.activityType isEqualToString:@"net.namedfork.keyboard"]) {
return [UISceneConfiguration configurationWithName:@"Keyboard" sessionRole:UIWindowSceneSessionRoleApplication];
}
}
if ([self sceneWithName:@"Default"] == nil) {
[[AppDelegate sharedEmulator] setRunning:YES];
return [UISceneConfiguration configurationWithName:@"Default" sessionRole:UIWindowSceneSessionRoleApplication];
}
return nil;
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
if ([self sceneWithName:@"Default"] == nil) {
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"runInBackground"] == NO) {
[[AppDelegate sharedEmulator] setRunning:NO];
}
UIScene *keyboardScene = [self sceneWithName:@"Keyboard"];
if (keyboardScene != nil) {
// if only keyboard is left, close it too
[application requestSceneSessionDestruction:keyboardScene.session options:nil errorHandler:nil];
}
}
}
- (UIScene*)sceneWithName:(NSString*)name {
for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
if ([scene.session.configuration.name isEqualToString:name]) {
return scene;
}
}
return nil;
}
@end

View File

@ -2,113 +2,110 @@
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
"scale" : "3x",
"size" : "20x20"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-Small@2x.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-Small@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-Small-40@2x-1.png",
"scale" : "2x"
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-Small-40@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "Icon-60@3x.png",
"scale" : "3x"
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
"scale" : "2x",
"size" : "20x20"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-Small.png",
"scale" : "1x"
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-Small@2x-1.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-Small-40.png",
"scale" : "1x"
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-Small-40@2x.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76.png",
"scale" : "1x"
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76@2x.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-iPadPro.png",
"scale" : "2x"
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"pre-rendered" : true
"author" : "xcode",
"version" : 1
}
}
}

View File

@ -0,0 +1,13 @@
{
"images" : [
{
"filename" : "back.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,12 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"frame-size" : {
"height" : 512,
"width" : 512
}
}
}

View File

@ -0,0 +1,17 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"layers" : [
{
"filename" : "Front.solidimagestacklayer"
},
{
"filename" : "Middle.solidimagestacklayer"
},
{
"filename" : "Back.solidimagestacklayer"
}
]
}

View File

@ -0,0 +1,13 @@
{
"images" : [
{
"filename" : "Icon.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

View File

@ -0,0 +1,12 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"frame-size" : {
"height" : 512,
"width" : 512
}
}
}

View File

@ -0,0 +1,13 @@
{
"images" : [
{
"filename" : "screen.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 B

View File

@ -0,0 +1,12 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"frame-size" : {
"height" : 512,
"width" : 512
}
}
}

View File

@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

View File

@ -23,6 +23,11 @@
"filename" : "KBCapsLock~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBCapsLock~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

View File

@ -23,6 +23,11 @@
"filename" : "KBClearDown~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBClearDown~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

View File

@ -23,6 +23,11 @@
"filename" : "KBClearUp~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBClearUp~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

View File

@ -23,6 +23,11 @@
"filename" : "KBCommand@2x~ipad.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBCommand@2x~ipad 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -23,6 +23,11 @@
"filename" : "KBDeleteDown~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBDeleteDown~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

View File

@ -23,6 +23,11 @@
"filename" : "KBDeleteUp~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBDeleteUp~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

View File

@ -23,6 +23,11 @@
"filename" : "KBForwardDeleteDown~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBForwardDeleteDown~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

View File

@ -23,6 +23,11 @@
"filename" : "KBForwardDeleteUp~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBForwardDeleteUp~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

View File

@ -1,6 +1,7 @@
{
"images" : [
{
"filename" : "KBHide~ipad 2.png",
"idiom" : "iphone",
"scale" : "1x"
},
@ -23,6 +24,11 @@
"filename" : "KBHide~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBHide~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

View File

@ -219,6 +219,25 @@
"mode" : "9-part"
},
"scale" : "2x"
},
{
"filename" : "KBKey@2x~ipad-2 1.png",
"idiom" : "vision",
"resizing" : {
"cap-insets" : {
"bottom" : 32,
"left" : 32,
"right" : 32,
"top" : 32
},
"center" : {
"height" : 2,
"mode" : "tile",
"width" : 2
},
"mode" : "9-part"
},
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

View File

@ -219,6 +219,25 @@
"mode" : "9-part"
},
"scale" : "2x"
},
{
"filename" : "KBKeyDark@2x~ipad-1 1.png",
"idiom" : "vision",
"resizing" : {
"cap-insets" : {
"bottom" : 32,
"left" : 32,
"right" : 32,
"top" : 32
},
"center" : {
"height" : 2,
"mode" : "tile",
"width" : 2
},
"mode" : "9-part"
},
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

View File

@ -23,6 +23,11 @@
"filename" : "KBNumPad@2x~ipad.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBNumPad@2x~ipad 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

View File

@ -23,6 +23,11 @@
"filename" : "KBOption@2x~ipad.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBOption@2x~ipad 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

View File

@ -23,6 +23,11 @@
"filename" : "KBShiftDown~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBShiftDown~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

View File

@ -23,6 +23,11 @@
"filename" : "KBShiftUp~ipad@2x.png",
"idiom" : "ipad",
"scale" : "2x"
},
{
"filename" : "KBShiftUp~ipad@2x 1.png",
"idiom" : "vision",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

View File

@ -1,23 +1,26 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "reset.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "reset@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "reset@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
}

View File

@ -1,23 +1,26 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "Settings.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "Settings@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "Settings@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
}

View File

@ -67,6 +67,6 @@ typedef uint64_t ui6b;
#define NeedIntlChars 1
#define kStrAppName "Mini vMac"
#define kAppVariationStr "minivmac-b37-ios"
#define kStrCopyrightYear "2022"
#define kStrCopyrightYear "2023"
#define kMaintainerName "Jesús A. Álvarez"
#define kStrHomePage "https://namedfork.net/minivmac"

View File

@ -0,0 +1,64 @@
//
// DefaultSceneDelegate.swift
// Mini vMac
//
// Created by Jesús A. Álvarez on 2024-02-09.
// Copyright © 2024 namedfork. All rights reserved.
//
import UIKit
class DefaultSceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow? // keep window reference to be able to set background colour before destroying
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else {
fatalError("Expected scene of type UIWindowScene but got an unexpected type")
}
guard let appDelegate = AppDelegate.shared else {
fatalError("No app delegate")
}
let size = CGSize(width: 1024.0, height: 684.0)
windowScene.sizeRestrictions?.minimumSize = size
windowScene.sizeRestrictions?.maximumSize = size
window = UIWindow(windowScene: windowScene)
if let window {
appDelegate.window = window
window.rootViewController = UIStoryboard(name: "Main", bundle: .main).instantiateInitialViewController()
window.makeKeyAndVisible()
}
self.destroyOtherSessions(not: session)
}
private func destroyOtherSessions(not session: UISceneSession) {
let app = UIApplication.shared
let options = UIWindowSceneDestructionRequestOptions()
options.windowDismissalAnimation = .decline
for otherSession in app.openSessions.filter({ $0 != session && $0.configuration.name == "Default"}) {
if let window = (otherSession.scene as? UIWindowScene)?.windows.first {
window.rootViewController?.view.removeFromSuperview()
window.backgroundColor = .darkGray
app.requestSceneSessionRefresh(otherSession)
}
app.requestSceneSessionDestruction(otherSession, options: options)
// window will remain visible until window switcher is dismissed!
}
}
func sceneDidEnterBackground(_ scene: UIScene) {
let app = UIApplication.shared
if UserDefaults.standard.bool(forKey: "runInBackground") == false && app.connectedScenes.filter({ $0 != scene && $0.session.configuration.name == "Default"}).isEmpty {
AppDelegate.emulator.isRunning = false
}
}
func sceneDidBecomeActive(_ scene: UIScene) {
AppDelegate.emulator.isRunning = true
}
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
AppDelegate.shared.application(UIApplication.shared, performActionFor: shortcutItem, completionHandler: completionHandler)
}
}

View File

@ -10,7 +10,7 @@
@import CoreGraphics;
@import QuartzCore;
typedef enum : NSInteger {
typedef NS_ENUM(NSInteger, EmulatorSpeed) {
EmulatorSpeedAllOut = -1,
EmulatorSpeed1x = 0,
EmulatorSpeed2x = 1,
@ -18,7 +18,7 @@ typedef enum : NSInteger {
EmulatorSpeed8x = 3,
EmulatorSpeed16x = 4,
EmulatorSpeed32x = 5
} EmulatorSpeed;
};
@protocol Emulator <NSObject>
@ -38,6 +38,9 @@ typedef enum : NSInteger {
@property (nonatomic, readonly) BOOL anyDiskInserted;
@property (nonatomic, readonly) NSString *currentApplication;
@property (nonatomic, strong) void (^showAlert)(NSString *title, NSString *message);
@property (nonatomic, strong) UIViewController *rootViewController;
- (void)run;
- (void)reset;
- (void)interrupt;

View File

@ -176,5 +176,28 @@
</dict>
</dict>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).DefaultSceneDelegate</string>
</dict>
<dict>
<key>UISceneConfigurationName</key>
<string>Keyboard</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).KeyboardSceneDelegate</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>

View File

@ -473,7 +473,7 @@
}
- (void)showFileActivityIndicatorWithTitle:(NSString*)title completion:(void (^_Nonnull)(UIActivityIndicatorView* activityIndicatorView))completionBlock {
UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
if (@available(iOS 13, *)) {
activityIndicatorView.color = [UIColor labelColor];
} else {

View File

@ -9,6 +9,12 @@
#import <UIKit/UIKit.h>
#import "KBKeyboardLayout.h"
#define KC_COMMAND 55
#define KC_SHIFT 56
#define KC_CAPSLOCK 57
#define KC_OPTION 58
#define KC_CONTROL 59
@class KBKey;
@protocol KBKeyboardViewDelegate <NSObject>
@ -22,6 +28,7 @@
@property (weak, nonatomic, nullable) id<KBKeyboardViewDelegate> delegate;
@property (nonatomic, strong, nullable) KBKeyboardLayout *layout;
@property (nonatomic, strong, nullable) UIMenu *layoutMenu;
@property (nonatomic, readonly, nonnull) NSArray<KBKey*>* keys;
@property (nonatomic, readonly, nonnull) NSArray<KBKey*>* stickyKeys;

View File

@ -9,26 +9,23 @@
#import "KBKeyboardView.h"
#import "KBKey.h"
#define KC_COMMAND 55
#define KC_SHIFT 56
#define KC_CAPSLOCK 57
#define KC_OPTION 58
#define KC_CONTROL 59
@implementation KBKeyboardView {
NSMutableArray *keyPlanes;
NSMutableArray *keyPlanes, *emptyKeyPlanes;
NSMutableSet *modifiers;
NSMutableIndexSet *keysDown;
CGAffineTransform defaultKeyTransform;
CGFloat fontSize;
CGSize selectedSize;
UIEdgeInsets safeAreaInsets;
CGSize intrinsicSize;
}
- (instancetype)initWithFrame:(CGRect)frame safeAreaInsets:(UIEdgeInsets)insets {
self = [super initWithFrame:frame];
if (self) {
safeAreaInsets = insets;
intrinsicSize = frame.size;
#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0
if (@available(iOS 13.0, *)) {
self.backgroundColor = [UIColor clearColor];
UIVisualEffectView *backgroundView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemThickMaterial]];
@ -37,8 +34,10 @@
} else {
self.backgroundColor = [UIColor colorWithRed:0xEB / 255.0 green:0xF0 / 255.0 blue:0xF7 / 255.0 alpha:0.9];
}
#endif
modifiers = [NSMutableSet setWithCapacity:4];
keysDown = [NSMutableIndexSet indexSet];
self.autoresizesSubviews = NO;
}
return self;
}
@ -47,10 +46,29 @@
return [self initWithFrame:frame safeAreaInsets:UIEdgeInsetsZero];
}
- (CGSize)intrinsicContentSize {
return intrinsicSize;
}
- (BOOL)isCompactKeyboardSize:(CGSize)size {
return size.width < 768.0;
}
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
- (void)layoutSubviews {
// TODO: optimize this if needed
CGSize size = self.bounds.size;
CGFloat scale = size.width / intrinsicSize.width;
CGAffineTransform transform = CGAffineTransformMakeScale(scale, scale);
if (!CGAffineTransformEqualToTransform(transform, defaultKeyTransform)) {
defaultKeyTransform = transform;
keyPlanes = emptyKeyPlanes.mutableCopy;
fontSize = 30.0 * scale;
[self switchToKeyPlane:0];
}
}
#endif
- (CGSize)findBestSizeForWidth:(CGFloat)preferredWidth inArray:(NSArray<NSValue*>*)sizes {
CGSize selectedSize = CGSizeZero;
for (NSValue *key in sizes) {
@ -116,7 +134,8 @@
for (int i = 0; i < numberOfKeyPlanes; i++) {
[keyPlanes addObject:[NSNull null]];
}
emptyKeyPlanes = keyPlanes.mutableCopy;
[self switchToKeyPlane:0];
}
@ -127,7 +146,16 @@
}
if (scancode == VKC_HIDE) {
key = [[KBHideKey alloc] initWithFrame:keyFrame];
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
if (self.layoutMenu != nil) {
key.showsMenuAsPrimaryAction = YES;
key.menu = self.layoutMenu;
} else {
return;
}
#else
[key addTarget:self action:@selector(hideKeyboard:) forControlEvents:UIControlEventTouchUpInside];
#endif
} else if (scancode == VKC_SHIFT_CAPS) {
key = [[KBShiftCapsKey alloc] initWithFrame:keyFrame];
key.scancode = KC_SHIFT;

View File

@ -0,0 +1,51 @@
//
// KeyboardSceneDelegate.swift
// Mini vMac
//
// Created by Jesús A. Álvarez on 2024-02-10.
// Copyright © 2024 namedfork. All rights reserved.
//
import UIKit
#if os(visionOS)
class KeyboardSceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else {
fatalError("Expected scene of type UIWindowScene but got an unexpected type")
}
guard let mainViewController = AppDelegate.shared.window.rootViewController as? ViewController else {
fatalError("No main view controller")
}
scene.activationConditions.canActivateForTargetContentIdentifierPredicate = NSPredicate(format: "self == 'net.namedfork.keyboard'", argumentArray: nil)
let defaultSize = mainViewController.keyboardViewController.preferredContentSize
let minSize = defaultSize.applying(.init(scaleX: 0.75, y: 0.75))
let maxSize = defaultSize.applying(.init(scaleX: 1.25, y: 1.25))
windowScene.sizeRestrictions?.minimumSize = minSize
windowScene.sizeRestrictions?.maximumSize = maxSize
windowScene.requestGeometryUpdate(UIWindowScene.GeometryPreferences.Vision(
size: defaultSize,
minimumSize: minSize,
maximumSize: maxSize,
resizingRestrictions: .uniform
))
window = UIWindow(windowScene: windowScene)
// destroy existing keyboard window
if let oldWindow = mainViewController.keyboardViewController?.view?.window {
oldWindow.rootViewController = nil
if let oldScene = oldWindow.windowScene?.session.scene {
UIApplication.shared.requestSceneSessionDestruction(oldScene.session, options: nil)
}
}
if let window {
window.rootViewController = mainViewController.keyboardViewController
window.makeKeyAndVisible()
}
}
}
#endif

View File

@ -1,13 +0,0 @@
//
// MNVMApplication.h
// Mini vMac
//
// Created by Jesús A. Álvarez on 14/05/2016.
// Copyright © 2016-2018 namedfork. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface MNVMApplication : UIApplication
@end

View File

@ -1,119 +0,0 @@
//
// MNVMApplication.m
// Mini vMac
//
// Created by Jesús A. Álvarez on 14/05/2016.
// Copyright © 2016-2018 namedfork. All rights reserved.
//
#import "MNVMApplication.h"
#import "AppDelegate.h"
@interface UIApplication ()
- (void)handleKeyUIEvent:(UIEvent *)event;
@end
Class keyboardEventClass = nil;
static int8_t usb_to_adb_scancode[] = {
-1, -1, -1, -1, 0, 11, 8, 2, 14, 3, 5, 4, 34, 38, 40, 37,
46, 45, 31, 35, 12, 15, 1, 17, 32, 9, 13, 7, 16, 6, 18, 19,
20, 21, 23, 22, 26, 28, 25, 29, 36, 53, 51, 48, 49, 27, 24, 33,
30, 42, 42, 41, 39, 10, 43, 47, 44, 57, 122, 120, 99, 118, 96, 97,
98, 100, 101, 109, 103, 111, 105, 107, 113, 114, 115, 116, 117, 119, 121, 60,
59, 61, 62, 71, 75, 67, 78, 69, 76, 83, 84, 85, 86, 87, 88, 89,
91, 92, 82, 65, 50, 55, 126, 81, 105, 107, 113, 106, 64, 79, 80, 90,
-1, -1, -1, -1, -1, 114, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74,
72, 73, -1, -1, -1, 95, -1, 94, -1, 93, -1, -1, -1, -1, -1, -1,
104, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54, 56, 58, 55, 54, 56, 58, 55, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
@interface UIPhysicalKeyboardEvent : UIPressesEvent
@property (nonatomic, readonly) BOOL _isKeyDown;
@property (nonatomic, readonly) long _keyCode;
@property (nonatomic) int _modifierFlags;
@property(retain, nonatomic) NSString *_unmodifiedInput;
@property(retain, nonatomic) NSString *_modifiedInput;
@end
@implementation MNVMApplication
{
BOOL physicalCapsLocked;
}
+ (void)load {
// class is not visible
keyboardEventClass = NSClassFromString(@"UIPhysicalKeyboardEvent");
}
- (void)handleKeyboardEvent:(UIPhysicalKeyboardEvent *)event {
long keycode = event._keyCode;
int scancode = -1;
if (keycode >= 0 && keycode < sizeof(usb_to_adb_scancode)) {
scancode = usb_to_adb_scancode[keycode];
}
if (scancode == 57) {
// caps lock
if (event._isKeyDown && !physicalCapsLocked) {
[[AppDelegate sharedEmulator] keyDown:scancode];
physicalCapsLocked = YES;
} else if (event._isKeyDown && physicalCapsLocked) {
[[AppDelegate sharedEmulator] keyUp:scancode];
physicalCapsLocked = NO;
}
} else if (scancode >= 0 && [AppDelegate sharedEmulator].running) {
if (event._isKeyDown) {
[self _updateCapsLockStatus:event];
[[AppDelegate sharedEmulator] keyDown:scancode];
} else {
[[AppDelegate sharedEmulator] keyUp:scancode];
}
}
}
- (void)_updateCapsLockStatus:(UIPhysicalKeyboardEvent *)event {
if (event._modifierFlags == 0 && event._unmodifiedInput.length == 1 && event._modifiedInput.length == 1) {
unichar unmodifiedChar = [event._unmodifiedInput characterAtIndex:0];
unichar modifiedChar = [event._modifiedInput characterAtIndex:0];
if ([[NSCharacterSet lowercaseLetterCharacterSet] characterIsMember:unmodifiedChar]) {
BOOL currentCapsLock = [[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:modifiedChar];
if (currentCapsLock != physicalCapsLocked) {
physicalCapsLocked = currentCapsLock;
if (physicalCapsLocked) {
[[AppDelegate sharedEmulator] keyDown:57];
} else {
[[AppDelegate sharedEmulator] keyUp:57];
}
}
}
}
}
- (void)handleKeyUIEvent:(UIEvent *)event {
[super handleKeyUIEvent:event];
static dispatch_once_t onceToken;
static BOOL handleKeyboardEvents = YES;
dispatch_once(&onceToken, ^{
if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) {
handleKeyboardEvents = [NSProcessInfo processInfo].operatingSystemVersion.majorVersion >= 9;
} else {
handleKeyboardEvents = NO;
}
});
BOOL emulatorIsFrontmost = [AppDelegate sharedEmulator].running && [AppDelegate sharedInstance].window.rootViewController.presentedViewController == nil;
if ([event isKindOfClass:keyboardEventClass] && handleKeyboardEvents && emulatorIsFrontmost) {
[self handleKeyboardEvent:(UIPhysicalKeyboardEvent*)event];
}
}
@end

View File

@ -1471,13 +1471,8 @@ LOCALPROC MacMsgDisplayOn() {
if (SavedBriefMsg != nullpr) {
NSString *title = NSStringCreateFromSubstCStr(SavedBriefMsg, falseblnr);
NSString *message = NSStringCreateFromSubstCStr(SavedLongMsg, falseblnr);
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
blnr wasStopped = SpeedStopped;
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
SpeedStopped = wasStopped;
}]];
sharedEmulator.showAlert(title, message);
SpeedStopped = trueblnr;
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
SavedBriefMsg = nullpr;
SavedLongMsg = nullpr;
}
@ -1642,6 +1637,8 @@ GLOBALPROC WaitForNextTick(void) {
}
@synthesize dataPath;
@synthesize showAlert;
@synthesize rootViewController;
- (instancetype)init {
if ((self = [super init])) {
@ -1792,7 +1789,7 @@ GLOBALPROC WaitForNextTick(void) {
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Save", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self didMakeNewDisk:self->nameTextField.text size:size];
}]];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
[sharedEmulator.rootViewController presentViewController:alertController animated:YES completion:nil];
}
- (void)didMakeNewDisk:(NSString*)fileName size:(NSInteger)size {

View File

@ -0,0 +1,47 @@
/*
see comment in OSGCOMUD.h
This file is automatically generated by the build system,
which tries to know what options are valid in what
combinations. Avoid changing this file manually unless
you know what you're doing.
*/
#define MySoundEnabled 1
#define MySoundRecenterSilence 0
#define kLn2SoundSampSz 3
#define dbglog_HAVE 0
#define WantAbnormalReports 0
#define NumDrives 6
#define NonDiskProtect 0
#define IncludeSonyRawMode 1
#define IncludeSonyGetName 1
#define IncludeSonyNew 1
#define IncludeSonyNameNew 1
#define vMacScreenHeight 384
#define vMacScreenWidth 512
#define vMacScreenDepth 3
#define kROM_Size 0x00040000
#define IncludePbufs 1
#define NumPbufs 4
#define EnableMouseMotion 1
#define IncludeHostTextClipExchange 1
#define EnableAutoSlow 1
#define EmLocalTalk 0
#define AutoLocation 1
#define AutoTimeZone 1
#define MNVMBundleClassName MacIIEmulator512x384
#ifdef PLIST_PREPROCESSOR
#define MNVMBundleDisplayName Mac II
#define MNVMBundleGetInfoString 8M, 512×384
#endif

View File

@ -0,0 +1,33 @@
/*
see comment in OSGCOMUD.h
This file is automatically generated by the build system,
which tries to know what options are valid in what
combinations. Avoid changing this file manually unless
you know what you're doing.
*/
#define RomFileName "MacII.ROM"
#define kCheckSumRom_Size 0x00040000
#define kRomCheckSum1 0x9779D2C4
#define kRomCheckSum2 0x97221136
#define RomStartCheckSum 1
#define SaveDialogEnable 1
#define EnableAltKeysMode 0
#define VarFullScreen 1
#define WantInitFullScreen 0
#define MayFullScreen 1
#define MayNotFullScreen 1
#define WantInitMagnify 0
#define EnableMagnify 1
#define MyWindowScale 2
#define WantInitRunInBackground 0
#define WantInitNotAutoSlow 0
#define WantInitSpeedValue 2
#define WantEnblCtrlInt 1
#define WantEnblCtrlRst 1
#define WantEnblCtrlKtg 1
#define UseControlKeys 1
#define UseActvCode 0
#define EnableDemoMsg 0

View File

@ -0,0 +1,238 @@
/*
see comment in PICOMMON.h
This file is automatically generated by the build system,
which tries to know what options are valid in what
combinations. Avoid changing this file manually unless
you know what you're doing.
*/
#define EmClassicKbrd 0
#define EmADB 1
#define EmRTC 1
#define EmPMU 0
#define EmVIA1 1
#define EmVIA2 1
#define Use68020 1
#define EmFPU 1
#define EmMMU 0
#define EmClassicSnd 0
#define EmASC 1
#define CurEmMd kEmMd_II
#define kMyClockMult 2
#define WantCycByPriOp 1
#define WantCloserCyc 0
#define kAutoSlowSubTicks 16384
#define kAutoSlowTime 60
#define kRAMa_Size 0x00400000
#define kRAMb_Size 0x00400000
#define IncludeVidMem 1
#define kVidMemRAM_Size 0x00080000
#define EmVidCard 1
#define kVidROM_Size 0x000800
#define MaxATTListN 20
#define IncludeExtnPbufs 1
#define IncludeExtnHostTextClipExchange 1
#define Sony_SupportDC42 1
#define Sony_SupportTags 0
#define Sony_WantChecksumsUpdated 0
#define Sony_VerifyChecksums 0
#define CaretBlinkTime 0x08
#define SpeakerVol 0x07
#define DoubleClickTime 0x08
#define MenuBlink 0x03
#define AutoKeyThresh 0x06
#define AutoKeyRate 0x03
#define pr_HilColRed 0x0000
#define pr_HilColGreen 0x0000
#define pr_HilColBlue 0x0000
/* the Wire variables are 1/0, not true/false */
enum {
Wire_unknown_SoundDisable,
#define SoundDisable (Wires[Wire_unknown_SoundDisable])
Wire_unknown_SoundVolb0,
#define SoundVolb0 (Wires[Wire_unknown_SoundVolb0])
Wire_unknown_SoundVolb1,
#define SoundVolb1 (Wires[Wire_unknown_SoundVolb1])
Wire_unknown_SoundVolb2,
#define SoundVolb2 (Wires[Wire_unknown_SoundVolb2])
Wire_VIA1_iA0_unknown,
#define VIA1_iA0 (Wires[Wire_VIA1_iA0_unknown])
Wire_VIA1_iA1_unknown,
#define VIA1_iA1 (Wires[Wire_VIA1_iA1_unknown])
Wire_VIA1_iA2_unknown,
#define VIA1_iA2 (Wires[Wire_VIA1_iA2_unknown])
Wire_VIA1_iB7_unknown, /* for compatibility with SoundDisable */
#define VIA1_iB7 (Wires[Wire_VIA1_iB7_unknown])
Wire_VIA2_InterruptRequest,
#define VIA2_InterruptRequest (Wires[Wire_VIA2_InterruptRequest])
#define VIA2_interruptChngNtfy VIAorSCCinterruptChngNtfy
Wire_VIA2_iA7_unknown,
#define VIA2_iA7 (Wires[Wire_VIA2_iA7_unknown])
#define VIA2_iA7_ChangeNtfy Addr32_ChangeNtfy
Wire_VIA2_iA6_unknown,
#define VIA2_iA6 (Wires[Wire_VIA2_iA6_unknown])
#define VIA2_iA6_ChangeNtfy Addr32_ChangeNtfy
Wire_VIA2_iB7_unknown,
#define VIA2_iB7 (Wires[Wire_VIA2_iB7_unknown])
Wire_VIA2_iCB2_unknown,
#define VIA2_iCB2 (Wires[Wire_VIA2_iCB2_unknown])
Wire_VIA2_iB2_PowerOff,
#define VIA2_iB2 (Wires[Wire_VIA2_iB2_PowerOff])
#define VIA2_iB2_ChangeNtfy PowerOff_ChangeNtfy
Wire_VIA2_iB3_Addr32,
#define VIA2_iB3 (Wires[Wire_VIA2_iB3_Addr32])
#define Addr32 (Wires[Wire_VIA2_iB3_Addr32])
#define VIA2_iB3_ChangeNtfy Addr32_ChangeNtfy
Wire_VIA1_iA4_MemOverlay,
#define MemOverlay (Wires[Wire_VIA1_iA4_MemOverlay])
#define VIA1_iA4 (Wires[Wire_VIA1_iA4_MemOverlay])
#define VIA1_iA4_ChangeNtfy MemOverlay_ChangeNtfy
Wire_VIA1_iA5_IWMvSel,
#define IWMvSel (Wires[Wire_VIA1_iA5_IWMvSel])
#define VIA1_iA5 (Wires[Wire_VIA1_iA5_IWMvSel])
Wire_VIA1_iA7_SCCwaitrq,
#define SCCwaitrq (Wires[Wire_VIA1_iA7_SCCwaitrq])
#define VIA1_iA7 (Wires[Wire_VIA1_iA7_SCCwaitrq])
Wire_VIA1_iB0_RTCdataLine,
#define RTCdataLine (Wires[Wire_VIA1_iB0_RTCdataLine])
#define VIA1_iB0 (Wires[Wire_VIA1_iB0_RTCdataLine])
#define VIA1_iB0_ChangeNtfy RTCdataLine_ChangeNtfy
Wire_VIA1_iB1_RTCclock,
#define RTCclock (Wires[Wire_VIA1_iB1_RTCclock])
#define VIA1_iB1 (Wires[Wire_VIA1_iB1_RTCclock])
#define VIA1_iB1_ChangeNtfy RTCclock_ChangeNtfy
Wire_VIA1_iB2_RTCunEnabled,
#define RTCunEnabled (Wires[Wire_VIA1_iB2_RTCunEnabled])
#define VIA1_iB2 (Wires[Wire_VIA1_iB2_RTCunEnabled])
#define VIA1_iB2_ChangeNtfy RTCunEnabled_ChangeNtfy
Wire_VIA1_iA3_SCCvSync,
#define VIA1_iA3 (Wires[Wire_VIA1_iA3_SCCvSync])
Wire_VIA1_iB3_ADB_Int,
#define ADB_Int (Wires[Wire_VIA1_iB3_ADB_Int])
#define VIA1_iB3 (Wires[Wire_VIA1_iB3_ADB_Int])
Wire_VIA1_iB4_ADB_st0,
#define ADB_st0 (Wires[Wire_VIA1_iB4_ADB_st0])
#define VIA1_iB4 (Wires[Wire_VIA1_iB4_ADB_st0])
#define VIA1_iB4_ChangeNtfy ADBstate_ChangeNtfy
Wire_VIA1_iB5_ADB_st1,
#define ADB_st1 (Wires[Wire_VIA1_iB5_ADB_st1])
#define VIA1_iB5 (Wires[Wire_VIA1_iB5_ADB_st1])
#define VIA1_iB5_ChangeNtfy ADBstate_ChangeNtfy
Wire_VIA1_iCB2_ADB_Data,
#define ADB_Data (Wires[Wire_VIA1_iCB2_ADB_Data])
#define VIA1_iCB2 (Wires[Wire_VIA1_iCB2_ADB_Data])
#define VIA1_iCB2_ChangeNtfy ADB_DataLineChngNtfy
Wire_VIA1_InterruptRequest,
#define VIA1_InterruptRequest (Wires[Wire_VIA1_InterruptRequest])
#define VIA1_interruptChngNtfy VIAorSCCinterruptChngNtfy
Wire_SCCInterruptRequest,
#define SCCInterruptRequest (Wires[Wire_SCCInterruptRequest])
#define SCCinterruptChngNtfy VIAorSCCinterruptChngNtfy
Wire_ADBMouseDisabled,
#define ADBMouseDisabled (Wires[Wire_ADBMouseDisabled])
Wire_VBLinterrupt,
#define Vid_VBLinterrupt (Wires[Wire_VBLinterrupt])
#define VIA2_iA0 (Wires[Wire_VBLinterrupt])
Wire_VBLintunenbl,
#define Vid_VBLintunenbl (Wires[Wire_VBLintunenbl])
kNumWires
};
/* VIA configuration */
#define VIA1_ORA_FloatVal 0xBF
/* bit 6 used to check version of hardware */
#define VIA1_ORB_FloatVal 0xFF
#define VIA1_ORA_CanIn 0x80
#define VIA1_ORA_CanOut 0x3F
#define VIA1_ORB_CanIn 0x09
#define VIA1_ORB_CanOut 0xB7
#define VIA1_IER_Never0 0x00
#define VIA1_IER_Never1 0x58
#define VIA1_CB2modesAllowed 0x01
#define VIA1_CA2modesAllowed 0x01
/* VIA 2 configuration */
#define VIA2_ORA_FloatVal 0xFF
#define VIA2_ORB_FloatVal 0xFF
#define VIA2_ORA_CanIn 0x01
#define VIA2_ORA_CanOut 0xC0
#define VIA2_ORB_CanIn 0x00
#define VIA2_ORB_CanOut 0x8C
#define VIA2_IER_Never0 0x00
#define VIA2_IER_Never1 0xED
#define VIA2_CB2modesAllowed 0x01
#define VIA2_CA2modesAllowed 0x01
#define Mouse_Enabled() (! ADBMouseDisabled)
#define VIA1_iCA1_PulseNtfy VIA1_iCA1_Sixtieth_PulseNtfy
#define Sixtieth_PulseNtfy VIA1_iCA1_Sixtieth_PulseNtfy
#define VIA1_iCA2_PulseNtfy VIA1_iCA2_RTC_OneSecond_PulseNtfy
#define RTC_OneSecond_PulseNtfy VIA1_iCA2_RTC_OneSecond_PulseNtfy
#define VIA2_iCA1_PulseNtfy VIA2_iCA1_Vid_VBLinterrupt_PulseNtfy
#define Vid_VBLinterrupt_PulseNotify VIA2_iCA1_Vid_VBLinterrupt_PulseNtfy
#define VIA2_iCB1_PulseNtfy VIA2_iCB1_ASC_interrupt_PulseNtfy
#define ASC_interrupt_PulseNtfy VIA2_iCB1_ASC_interrupt_PulseNtfy
#define GetSoundInvertTime VIA1_GetT1InvertTime
#define ADB_ShiftInData VIA1_ShiftOutData
#define ADB_ShiftOutData VIA1_ShiftInData
#define kExtn_Block_Base 0x50F0C000
#define kExtn_ln2Spc 5
#define kROM_Base 0x00800000
#define kROM_ln2Spc 20
#define WantDisasm 0
#define ExtraAbnormalReports 0

View File

@ -0,0 +1,9 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "ViewController.h"
#import "AppDelegate.h"
#import "EmulatorProtocol.h"
#import "KBKeyboardView.h"
#import "KBKeyboardLayout.h"

35
Mini vMac/PowerMenu.swift Normal file
View File

@ -0,0 +1,35 @@
//
// PowerMenu.swift
// Mini vMac
//
// Created by Jesús A. Álvarez on 2024-02-10.
// Copyright © 2024 namedfork. All rights reserved.
//
import SwiftUI
#if os(visionOS)
struct PowerMenu: View {
var body: some View {
Menu() {
Section("Power") {
Button("Restart", systemImage: "arrowtriangle.right", role: .destructive) {
AppDelegate.shared.loadAndStartEmulator()
}
Button("Interrupt", systemImage: "arrowtriangle.down.circle", role: .destructive) {
AppDelegate.emulator.interrupt()
}
Button("Shut Down", systemImage: "minus.circle", role: .destructive) {
exit(0)
}
}
} label: {
Image(systemName: "power")
}.menuOrder(.fixed)
}
}
#Preview {
PowerMenu()
}
#endif

View File

@ -29,7 +29,7 @@ static ScreenView *sharedScreenView = nil;
[self updateVideoLayer];
[self.layer addSublayer:videoLayer];
[[AppDelegate sharedInstance] addObserver:self forKeyPath:@"sharedEmulator" options:NSKeyValueObservingOptionNew context:NULL];
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"screenFilter" options:NSKeyValueObservingOptionNew context:NULL];
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"screenFilter" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
}
+ (instancetype)sharedScreenView {
@ -57,17 +57,25 @@ static ScreenView *sharedScreenView = nil;
- (void)layoutSubviews {
[super layoutSubviews];
CGRect viewBounds = self.bounds;
CGFloat screenScale = MAX(screenSize.width / viewBounds.size.width, screenSize.height / viewBounds.size.height);
if (screenScale > 0.9 && screenScale <= 1.0) {
CGFloat screenScale = MIN(viewBounds.size.width / screenSize.width, viewBounds.size.height / screenSize.height);
NSString *screenFilter = [[NSUserDefaults standardUserDefaults] stringForKey:@"screenFilter"];
if ([screenFilter isEqualToString:kCAFilterNearest] && screenScale > 1.0) {
screenScale = floor(screenScale);
} else if (screenScale > 1.0 && screenScale <= 1.1) {
screenScale = 1.0;
}
screenBounds = CGRectMake(0, 0, screenSize.width / screenScale, screenSize.height / screenScale);
screenBounds = CGRectMake(0, 0, screenSize.width * screenScale, screenSize.height * screenScale);
screenBounds.origin.x = (viewBounds.size.width - screenBounds.size.width)/2;
screenBounds = CGRectIntegral(screenBounds);
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && (viewBounds.size.height - screenBounds.size.height) >= 30.0) {
// move under multitasking indicator on iPad
screenBounds.origin.y += 30;
}
videoLayer.frame = screenBounds;
screenBounds.origin.y = self.frame.origin.y;
screenBounds.origin.y += self.frame.origin.y;
BOOL scaleIsIntegral = (floor(screenScale) == screenScale);
NSString *screenFilter = scaleIsIntegral ? kCAFilterNearest : [[NSUserDefaults standardUserDefaults] stringForKey:@"screenFilter"];
if (scaleIsIntegral) screenFilter = kCAFilterNearest;
videoLayer.magnificationFilter = screenFilter;
videoLayer.minificationFilter = screenFilter;
}
@ -75,13 +83,19 @@ static ScreenView *sharedScreenView = nil;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if ([object isEqual:[NSUserDefaults standardUserDefaults]]) {
if ([keyPath isEqualToString:@"screenFilter"]) {
NSString *oldValue = change[NSKeyValueChangeOldKey];
NSString *value = change[NSKeyValueChangeNewKey];
videoLayer.magnificationFilter = value;
videoLayer.minificationFilter = value;
if ([value isEqualToString:kCAFilterNearest] || [oldValue isEqualToString:kCAFilterNearest]) {
[self setNeedsLayout];
[self layoutIfNeeded];
}
}
} else if (object == [AppDelegate sharedInstance] && [keyPath isEqualToString:@"sharedEmulator"]) {
[self updateVideoLayer];
[self layoutSubviews];
[self setNeedsLayout];
[self layoutIfNeeded];
}
}

View File

@ -0,0 +1,141 @@
//
// SettingsMenu.swift
// Mini vMac
//
// Created by Jesús A. Álvarez on 2024-02-10.
// Copyright © 2024 namedfork. All rights reserved.
//
import SwiftUI
#if os(visionOS)
struct SettingsMenu: View {
var body: some View {
Menu() {
Section("Settings") {
SpeedMenu()
MachineMenu()
DisplayScalingMenu()
}
} label: {
Image(systemName: "gear")
}.menuOrder(.fixed)
}
}
struct SpeedMenu: View {
@AppStorage("speedValue") var currentSpeed: EmulatorSpeed = .speed1x
@AppStorage("runInBackground") var runInBackground: Bool = false
private var currentSpeedImage: String {
switch currentSpeed {
case .speed1x:
"tortoise"
case .speedAllOut:
"hare"
case .speed2x:
"2.square"
case .speed4x:
"4.square"
case .speed8x:
"8.square"
case .speed16x:
"16.square"
case .speed32x:
"32.square"
@unknown default:
"hare"
}
}
var body: some View {
Menu("Speed", systemImage:currentSpeedImage) {
SpeedButton(label: "1x", speed: .speed1x)
SpeedButton(label: "2x", speed: .speed2x)
SpeedButton(label: "4x", speed: .speed4x)
SpeedButton(label: "8x", speed: .speed8x)
SpeedButton(label: "16x", speed: .speed16x)
SpeedButton(label: "32x", speed: .speed32x)
SpeedButton(label: "Unlimited", speed: .speedAllOut)
Divider()
Toggle("Run in Background", isOn: $runInBackground)
}.menuOrder(.fixed)
}
}
struct SpeedButton: View {
@AppStorage("speedValue") var currentSpeed: EmulatorSpeed = .speed1x
let label: LocalizedStringKey
let speed: EmulatorSpeed
var body: some View {
Toggle(label, isOn: Binding(get: {
currentSpeed == speed
}, set: { enable in
if enable {
currentSpeed = speed
}
}))
}
}
struct MachineMenu: View {
@AppStorage("machine") var currentMachine: String = "Plus4M"
let bundles = AppDelegate.shared.emulatorBundles?.sorted(by: { $0.bundleIdentifier! < $1.bundleIdentifier! }) ?? []
var body: some View {
Menu("Machine", systemImage: "desktopcomputer") {
ForEach(bundles, id: \.bundleIdentifier) { bundle in
MachineButton(bundle: bundle)
}
}.menuOrder(.fixed)
}
}
struct MachineButton: View {
@AppStorage("machine") var currentMachine: String = "Plus4M"
var bundle: Bundle
var body: some View {
Toggle(isOn: Binding(get: {
currentMachine == bundle.name
}, set: { enable in
if enable && !AppDelegate.emulator.anyDiskInserted {
currentMachine = bundle.name
AppDelegate.shared.loadAndStartEmulator()
}
}), label: {
Text("\(bundle.displayName ?? bundle.name)\n\(bundle.getInfoString ?? "")")
})
}
}
fileprivate extension Bundle {
var name: String { ((self.bundlePath as NSString).lastPathComponent as NSString).deletingPathExtension }
var displayName: String? { self.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String }
var getInfoString: String? { self.object(forInfoDictionaryKey: "CFBundleGetInfoString") as? String }
}
struct DisplayScalingMenu: View {
@AppStorage("screenFilter") var scalingFilter: CALayerContentsFilter = .nearest
static let filters = [
DisplayScalingFilter(filter: .nearest, name: "Nearest"),
DisplayScalingFilter(filter: .linear, name: "Linear"),
DisplayScalingFilter(filter: .trilinear, name: "Trilinear"),
]
var body: some View {
Menu("Display Scaling", systemImage: "rectangle.and.text.magnifyingglass") {
ForEach(DisplayScalingMenu.filters, id: \.filter) { filter in
Toggle(filter.name, isOn: Binding(get: {
scalingFilter == filter.filter
}, set: { enable in
if enable {
scalingFilter = filter.filter
}
}))
}
}.menuOrder(.fixed)
}
}
struct DisplayScalingFilter {
let filter: CALayerContentsFilter
let name: String
}
#endif

View File

@ -37,12 +37,7 @@ typedef enum : NSInteger {
- (void)viewDidLoad {
[super viewDidLoad];
keyboardLayouts = [[NSBundle mainBundle] pathsForResourcesOfType:@"nfkeyboardlayout" inDirectory:@"Keyboard Layouts"];
NSString *userKeyboardLayoutsPath = [AppDelegate sharedInstance].userKeyboardLayoutsPath;
NSArray *userKeyboardLayouts = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:userKeyboardLayoutsPath error:nil] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"pathExtension.lowercaseString = %@", @"nfkeyboardlayout"]];
if (userKeyboardLayouts.count > 0) {
keyboardLayouts = [keyboardLayouts arrayByAddingObjectsFromArray:userKeyboardLayouts];
}
keyboardLayouts = [AppDelegate sharedInstance].keyboardLayoutPaths;
[self loadEmulatorBundles];
[self loadCredits];
}
@ -177,7 +172,11 @@ typedef enum : NSInteger {
case SettingsSectionMachine:
return machineList.count;
case SettingsSectionAbout:
#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0
return aboutItems.count + 1;
#else
return aboutItems.count;
#endif
default:
return 1;
}
@ -372,7 +371,7 @@ typedef enum : NSInteger {
// links in about
NSString *linkURL = aboutItems[indexPath.row][@"link"];
if (linkURL != nil) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkURL]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkURL] options:@{} completionHandler:nil];
}
}
}

View File

@ -46,12 +46,7 @@
}
- (BOOL)isMouseEvent:(UIEvent *)event {
#if __IPHONE_13_4
if (@available(iOS 13.4, *)) {
return event.buttonMask != 0;
}
#endif
return NO;
return event.buttonMask != 0;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

View File

@ -18,6 +18,15 @@
- (IBAction)showGestureHelp:(id)sender;
- (IBAction)hideGestureHelp:(id)sender;
- (void)showKeyboard:(id)sender;
@end
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
@interface ViewController (VisionSupport)
@property (nonatomic, readonly) UIViewController* keyboardViewController;
- (void)initXr;
+ (void)adjustToScreenSize;
- (UIMenu*)keyboardLayoutMenu;
@end
#endif

View File

@ -13,50 +13,91 @@
#import "KBKeyboardView.h"
#import "KBKeyboardLayout.h"
@interface ViewController () <UIAdaptivePresentationControllerDelegate>
@interface ViewController () <UIAdaptivePresentationControllerDelegate, UIPointerInteractionDelegate>
@end
#ifdef __IPHONE_13_4
API_AVAILABLE(ios(13.4))
@interface ViewController (PointerInteraction) <UIPointerInteractionDelegate>
@end
#endif
static int8_t usb_to_adb_scancode[] = {
-1, -1, -1, -1, 0, 11, 8, 2, 14, 3, 5, 4, 34, 38, 40, 37,
46, 45, 31, 35, 12, 15, 1, 17, 32, 9, 13, 7, 16, 6, 18, 19,
20, 21, 23, 22, 26, 28, 25, 29, 36, 53, 51, 48, 49, 27, 24, 33,
30, 42, 42, 41, 39, 10, 43, 47, 44, 57, 122, 120, 99, 118, 96, 97,
98, 100, 101, 109, 103, 111, 105, 107, 113, 114, 115, 116, 117, 119, 121, 60,
59, 61, 62, 71, 75, 67, 78, 69, 76, 83, 84, 85, 86, 87, 88, 89,
91, 92, 82, 65, 50, 55, 126, 81, 105, 107, 113, 106, 64, 79, 80, 90,
-1, -1, -1, -1, -1, 114, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74,
72, 73, -1, -1, -1, 95, -1, 94, -1, 93, -1, -1, -1, -1, -1, -1,
104, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54, 56, 58, 55, 54, 56, 58, 55, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
@implementation ViewController
{
KBKeyboardView *keyboardView;
UISwipeGestureRecognizer *showKeyboardGesture, *hideKeyboardGesture, *insertDiskGesture, *showSettingsGesture;
UIControl *pointingDeviceView;
id interaction;
}
- (Point)mouseLocForCGPoint:(CGPoint)point {
Point mouseLoc;
CGRect screenBounds = self.screenView.screenBounds;
CGSize screenSize = self.screenView.screenSize;
mouseLoc.h = (point.x - screenBounds.origin.x) * (screenSize.width/screenBounds.size.width);
mouseLoc.v = (point.y - screenBounds.origin.y) * (screenSize.height/screenBounds.size.height);
return mouseLoc;
UIViewController *_keyboardViewController;
BOOL physicalCapsLocked;
UIPointerInteraction *pointerInteraction;
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(emulatorDidShutDown:) name:[AppDelegate sharedEmulator].shutdownNotification object:nil];
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
[self initXr];
#else
[self scheduleHelpPresentationIfNeededAfterDelay:6.0];
[self installGestures];
#endif
}
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
- (UIViewController *)keyboardViewController {
if (keyboardView == nil) {
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"keyboardLayout" options:0 context:NULL];
KBKeyboardLayout *layout = [self keyboardLayout];
CGSize keyboardSize = CGSizeZero;
for (NSValue *size in layout.availableSizes) {
if (size.CGSizeValue.width > keyboardSize.width) {
keyboardSize = size.CGSizeValue;
}
}
keyboardView = [[KBKeyboardView alloc] initWithFrame:CGRectMake(0, 0, keyboardSize.width, keyboardSize.height)];
keyboardView.layoutMenu = [self keyboardLayoutMenu];
keyboardView.layout = layout;
keyboardView.delegate = self;
}
if (_keyboardViewController == nil) {
_keyboardViewController = [UIViewController alloc];
_keyboardViewController.view = keyboardView;
_keyboardViewController.preferredContentSize = keyboardView.frame.size;
} else if (_keyboardViewController.view != keyboardView) {
_keyboardViewController.view = keyboardView;
}
return _keyboardViewController;
}
#endif
- (void)installGestures {
[self installKeyboardGestures];
insertDiskGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(showInsertDisk:)];
insertDiskGesture.direction = UISwipeGestureRecognizerDirectionLeft;
insertDiskGesture.numberOfTouchesRequired = 2;
[self.view addGestureRecognizer:insertDiskGesture];
showSettingsGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(showSettings:)];
showSettingsGesture.direction = UISwipeGestureRecognizerDirectionRight;
showSettingsGesture.numberOfTouchesRequired = 2;
[self.view addGestureRecognizer:showSettingsGesture];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(emulatorDidShutDown:) name:[AppDelegate sharedEmulator].shutdownNotification object:nil];
[self scheduleHelpPresentationIfNeededAfterDelay:6.0];
}
- (void)showSettings:(id)sender {
@ -75,6 +116,11 @@ API_AVAILABLE(ios(13.4))
[self dismissViewControllerAnimated:YES completion:nil];
}
}
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
if ([segue.identifier isEqualToString:@"disk"]) {
[(UINavigationController*)segue.destinationViewController setToolbarHidden:YES];
}
#endif
}
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController {
@ -90,6 +136,7 @@ API_AVAILABLE(ios(13.4))
}
}
#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0
- (BOOL)prefersStatusBarHidden {
UIScreen *screen = self.view.window.screen;
return CGRectEqualToRect(screen.bounds, self.view.window.bounds);
@ -98,6 +145,7 @@ API_AVAILABLE(ios(13.4))
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
#endif
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
return UIRectEdgeAll;
@ -113,29 +161,8 @@ API_AVAILABLE(ios(13.4))
[[NSUserDefaults standardUserDefaults] removeObserver:self forKeyPath:@"trackpad"];
}
- (void)setUpPointingDevice {
if (pointingDeviceView) {
[pointingDeviceView removeFromSuperview];
pointingDeviceView = nil;
}
#ifdef __IPHONE_13_4
if (@available(iOS 13.4, *)) {
if (interaction == nil) {
interaction = [[UIPointerInteraction alloc] initWithDelegate: self];
[self.view addInteraction:interaction];
}
}
#endif
BOOL useTrackPad = [[NSUserDefaults standardUserDefaults] boolForKey:@"trackpad"];
Class pointingDeviceClass = useTrackPad ? [TrackPad class] : [TouchScreen class];
pointingDeviceView = [[pointingDeviceClass alloc] initWithFrame:self.view.bounds];
pointingDeviceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view insertSubview:pointingDeviceView aboveSubview:self.screenView];
if ([UIApplication instancesRespondToSelector:@selector(btcMouseSetRawMode:)]) {
[[UIApplication sharedApplication] btcMouseSetRawMode:YES];
}
- (BOOL)prefersHomeIndicatorAutoHidden {
return YES;
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
@ -147,6 +174,11 @@ API_AVAILABLE(ios(13.4))
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if (object == [NSUserDefaults standardUserDefaults]) {
if ([keyPath isEqualToString:@"keyboardLayout"] && keyboardView != nil) {
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
// FIXME: do this nicelier
keyboardView = nil;
[self keyboardViewController];
#else
BOOL keyboardWasVisible = self.keyboardVisible;
[self setKeyboardVisible:NO animated:NO];
[keyboardView removeFromSuperview];
@ -154,6 +186,7 @@ API_AVAILABLE(ios(13.4))
if (keyboardWasVisible) {
[self setKeyboardVisible:YES animated:NO];
}
#endif
} else if ([keyPath isEqualToString:@"trackpad"]) {
[self setUpPointingDevice];
}
@ -213,7 +246,9 @@ API_AVAILABLE(ios(13.4))
#pragma mark - Gesture Help
- (void)showGestureHelp:(id)sender {
#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0
[self setGestureHelpHidden:NO];
#endif
}
- (void)hideGestureHelp:(id)sender {
@ -269,7 +304,11 @@ API_AVAILABLE(ios(13.4))
}
- (BOOL)isKeyboardVisible {
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
return _keyboardViewController.view.window != nil;
#else
return keyboardView != nil && CGRectIntersectsRect(keyboardView.frame, self.view.bounds) && !keyboardView.hidden;
#endif
}
- (void)setKeyboardVisible:(BOOL)keyboardVisible {
@ -285,10 +324,24 @@ API_AVAILABLE(ios(13.4))
}
- (void)setKeyboardVisible:(BOOL)visible animated:(BOOL)animated {
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
if (visible) {
UISceneSessionActivationRequest *request = [UISceneSessionActivationRequest requestWithRole:UIWindowSceneSessionRoleApplication];
request.userActivity = [[NSUserActivity alloc] initWithActivityType:@"net.namedfork.keyboard"];
request.userActivity.targetContentIdentifier = @"net.namedfork.keyboard";
[[UIApplication sharedApplication] activateSceneSessionForRequest:request errorHandler:^(NSError * _Nonnull error) {
NSLog(@"Activation error: %@", error);
}];
} else {
UIScene *keyboardScene = [[AppDelegate sharedInstance] sceneWithName:@"Keyboard"];
if (keyboardScene != nil) {
[[UIApplication sharedApplication] requestSceneSessionDestruction:keyboardScene.session options:nil errorHandler:nil];
}
}
#else
if (self.keyboardVisible == visible) {
return;
}
if (visible) {
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"keyboardLayout" options:0 context:NULL];
[self loadKeyboardView];
@ -322,7 +375,7 @@ API_AVAILABLE(ios(13.4))
keyboardView.hidden = YES;
}
}
#endif
}
- (void)loadKeyboardView {
@ -364,16 +417,106 @@ API_AVAILABLE(ios(13.4))
[[AppDelegate sharedEmulator] keyUp:scancode];
}
@end
#ifdef __IPHONE_13_4
API_AVAILABLE(ios(13.4))
@implementation ViewController (PointerInteraction)
- (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)){
if (request != nil) {
Point mouseLoc = [self mouseLocForCGPoint:request.location];
[[AppDelegate sharedEmulator] setMouseX:mouseLoc.h Y:mouseLoc.v];
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
for (UIPress *press in presses) {
[self handlePressEvent:press];
}
}
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
for (UIPress *press in presses) {
[self handlePressEvent:press];
}
}
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
for (UIPress *press in presses) {
[self handlePressEvent:press];
}
}
- (void)handlePressEvent:(UIPress *)event {
long keycode = event.key.keyCode;
int scancode = -1;
BOOL emulatorIsFrontmost = [AppDelegate sharedEmulator].running && [AppDelegate sharedInstance].window.rootViewController.presentedViewController == nil;
BOOL isKeyDown = (event.phase == UIPressPhaseBegan);
if (keycode >= 0 && keycode < sizeof(usb_to_adb_scancode)) {
scancode = usb_to_adb_scancode[keycode];
}
if (scancode == KC_CAPSLOCK) {
// caps lock
if (isKeyDown && !physicalCapsLocked) {
[[AppDelegate sharedEmulator] keyDown:KC_CAPSLOCK];
physicalCapsLocked = YES;
} else if (isKeyDown && physicalCapsLocked) {
[[AppDelegate sharedEmulator] keyUp:KC_CAPSLOCK];
physicalCapsLocked = NO;
}
} else if (scancode >= 0 && emulatorIsFrontmost) {
[self _updateCapsLockStatus:event];
if (isKeyDown) {
[[AppDelegate sharedEmulator] keyDown:scancode];
} else {
[[AppDelegate sharedEmulator] keyUp:scancode];
}
}
}
- (void)_updateCapsLockStatus:(UIPress *)event {
BOOL currentCapsLock = (event.key.modifierFlags & UIKeyModifierAlphaShift) != 0;
if (currentCapsLock != physicalCapsLocked) {
physicalCapsLocked = currentCapsLock;
if (physicalCapsLocked) {
[[AppDelegate sharedEmulator] keyDown:KC_CAPSLOCK];
} else {
[[AppDelegate sharedEmulator] keyUp:KC_CAPSLOCK];
}
}
}
#pragma mark - Mouse
- (void)setUpPointingDevice {
if (pointingDeviceView) {
[pointingDeviceView removeFromSuperview];
pointingDeviceView = nil;
}
if (pointerInteraction == nil) {
pointerInteraction = [[UIPointerInteraction alloc] initWithDelegate: self];
[self.view addInteraction:pointerInteraction];
UIHoverGestureRecognizer *hoverGestureRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(hover:)];
[self.view addGestureRecognizer:hoverGestureRecognizer];
}
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
Class pointingDeviceClass = [TouchScreen class];
#else
BOOL useTrackPad = [[NSUserDefaults standardUserDefaults] boolForKey:@"trackpad"];
Class pointingDeviceClass = useTrackPad ? [TrackPad class] : [TouchScreen class];
#endif
pointingDeviceView = [[pointingDeviceClass alloc] initWithFrame:self.view.bounds];
pointingDeviceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view insertSubview:pointingDeviceView aboveSubview:self.screenView];
if ([UIApplication instancesRespondToSelector:@selector(btcMouseSetRawMode:)]) {
[[UIApplication sharedApplication] btcMouseSetRawMode:YES];
}
}
- (Point)mouseLocForCGPoint:(CGPoint)point {
Point mouseLoc;
CGRect screenBounds = self.screenView.screenBounds;
CGSize screenSize = self.screenView.screenSize;
mouseLoc.h = (point.x - screenBounds.origin.x) * (screenSize.width/screenBounds.size.width);
mouseLoc.v = (point.y - screenBounds.origin.y) * (screenSize.height/screenBounds.size.height);
return mouseLoc;
}
- (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion {
return defaultRegion;
}
@ -381,5 +524,9 @@ API_AVAILABLE(ios(13.4))
return [UIPointerStyle hiddenPointerStyle];
}
- (void)hover:(UIHoverGestureRecognizer *)hoverGestureRecognizer {
Point mouseLoc = [self mouseLocForCGPoint:[hoverGestureRecognizer locationInView:self.screenView]];
[[AppDelegate sharedEmulator] setMouseX:mouseLoc.h Y:mouseLoc.v];
}
@end
#endif

View File

@ -0,0 +1,80 @@
//
// VisionSupport.swift
// Mini vMac
//
// Created by Jesús A. Álvarez on 2024-02-09.
// Copyright © 2024 namedfork. All rights reserved.
//
import Foundation
import UIKit
import SwiftUI
extension ViewController {
#if os(visionOS)
@objc
func initXr() {
ViewController.adjustToScreenSize()
ornaments = [
UIHostingOrnament(sceneAnchor: .bottom, contentAlignment: .center) {
VStack {
Spacer(minLength: 80.0)
HStack {
PowerMenu()
SettingsMenu()
Button(action: {
AppDelegate.shared.showInsertDisk(self)
}, label: {
Image(systemName: "opticaldiscdrive")
})
Button(action: {
self.showKeyboard(self)
}, label: {
Image(systemName: "keyboard")
})
}
.padding(.all)
.glassBackgroundEffect()
}
}
]
}
@objc
static func adjustToScreenSize() {
let screenSize = AppDelegate.emulator.screenSize
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
return
}
let minSize = screenSize
let defaultSize = screenSize.applying(.init(scaleX: 2.0, y: 2.0))
let maxSize = screenSize.applying(.init(scaleX: 3.0, y: 3.0))
windowScene.sizeRestrictions?.minimumSize = minSize
windowScene.sizeRestrictions?.maximumSize = maxSize
windowScene.requestGeometryUpdate(UIWindowScene.GeometryPreferences.Vision(
size: defaultSize,
minimumSize: minSize,
maximumSize: maxSize,
resizingRestrictions: .uniform
))
}
@objc
func keyboardLayoutMenu() -> UIMenu {
let layouts = AppDelegate.shared.keyboardLayoutPaths ?? []
let items: [UIMenuElement] = layouts.map({ path in
UIDeferredMenuElement.uncached { completion in
let layoutId = (path as NSString).lastPathComponent
let displayName = (layoutId as NSString).deletingPathExtension
let selected = UserDefaults.standard.string(forKey: "keyboardLayout") == layoutId
completion([UIAction(title: displayName, state: selected ? .on : .off) { _ in
UserDefaults.standard.setValue(layoutId, forKey: "keyboardLayout")
}])
}
})
return UIMenu(title: "Layout", options: [], children: items)
}
#endif
}

View File

@ -18,7 +18,7 @@
<key>detailText</key>
<string>Jesús A. Álvarez</string>
<key>link</key>
<string>https://twitter.com/maczydeco</string>
<string>https://mastodon.social/@maczydeco</string>
</dict>
<dict>
<key>text</key>
@ -39,7 +39,7 @@
</array>
<key>footer.html</key>
<string>Mini vMac for iOS&lt;br/&gt;
©2008-2022 Jesús A. Álvarez&lt;br/&gt;
©2008-2023 Jesús A. Álvarez&lt;br/&gt;
&lt;a href=&quot;https://namedfork.net/minivmac&quot;&gt;namedfork.net/minivmac&lt;/a&gt;&lt;br/&gt;
&lt;hr/&gt;
based on Mini vMac $mnvmversion&lt;br/&gt;

View File

@ -11,6 +11,6 @@
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, @"MNVMApplication", NSStringFromClass([AppDelegate class]));
return UIApplicationMain(argc, argv, NSStringFromClass([UIApplication class]), NSStringFromClass([AppDelegate class]));
}
}

View File

@ -5,13 +5,14 @@
* Emulates Mac Plus, Mac II or Mac 128K
* Full simulated keyboard (including all Mac keys)
* Full sound output
* Uses external keyboard if available
* Uses external keyboard and mouse/trackpad if available
* Regulable emulation speed
* Easy(ish) to import/export disk images
## Requirements
* iOS 9 or later
* iOS/iPadOS 13.4 or later, or visionOS
* Previous versions support down to iOS 7
* ROM image from Mac Plus, Mac II and/or Mac 128K
* Disk images with Mac software
@ -59,9 +60,6 @@ dragging on supported devices.
If you use a mouse or trackpad on iPad OS 13.4 or newer, it will be used automatically.
If you have a jailbroken device and [BTC Mouse & Trackpad](http://www.ringwald.ch/cydia/mouse/),
Mini vMac will use your bluetooth mouse or trackpad.
### Settings
Swipe right with two fingers to show the settings dialog, where you can change
@ -73,7 +71,35 @@ the following:
* **Display Scaling:** choose how to scale the display
* **Emulated Machine:** changes won't take effect if there are disks inserted
### Credits
## Installation
The easiest way is to install an IPA from [releases](https://github.com/zydeco/minivmac4ios/releases) with [AltStore](https://altstore.io).
### Building from source
To build the project, make sure you check out the repository and submodules:
```
git clone https://github.com/zydeco/minivmac4ios.git
cd minivmac4ios
git submodule update --init --recursive
```
The folders `minivmac`, `libmfs` and `libres` should not be empty. The source code zip file you can download from GitHub does not include all dependencies.
To install run the app on your device with Xcode, you'll to perform some [additoinal steps](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device):
* Pair the device with Xcode
* Specify your Apple ID in the Account preferences in Xcode.
* Change the Team (to your own) and Bundle Identifier (for example, change the `net.namedfork` prefix to your own) in the “Mini vMac” target, under the “Signing & Capabilities” tab.
* Enable [Developer Mode](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device) on your device (iOS 16 and later).
* On older iOS versions, trust your developer profile in the iOS Settings (under General > Device Management) after installing the app for the first time.
## Adding new emulated machines
See documentation [on the wiki](https://github.com/zydeco/minivmac4ios/wiki/Adding-a-new-emulated-machine).
## Credits
* Mini vMac for iOS by [Jesús A. Álvarez](https://github.com/zydeco)
* [Mini vMac](http://gryphel.com/c/minivmac/) ©2001-2021 Paul C. Pratt