2.4
This commit is contained in:
parent
94343b3f3b
commit
834b7e6b02
@ -18,6 +18,7 @@ struct ContentView: View {
|
|||||||
@AppStorage("useTrollStore") var useTrollStore: Bool = false
|
@AppStorage("useTrollStore") var useTrollStore: Bool = false
|
||||||
@AppStorage("showMetalHUD") var showMetalHUD: Bool = false
|
@AppStorage("showMetalHUD") var showMetalHUD: Bool = false
|
||||||
@AppStorage("canShowMetalHUD") var canShowMetalHUD: Bool = false
|
@AppStorage("canShowMetalHUD") var canShowMetalHUD: Bool = false
|
||||||
|
@AppStorage("HideMenuButton") private var HideMenuButton: Bool = true
|
||||||
@State var core = Core(games: [], root: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0])
|
@State var core = Core(games: [], root: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0])
|
||||||
var body: some View {
|
var body: some View {
|
||||||
//NavView(core: $core) // pain and suffering
|
//NavView(core: $core) // pain and suffering
|
||||||
|
@ -38,7 +38,10 @@ class SudachiEmulationViewModel: ObservableObject {
|
|||||||
|
|
||||||
iscustom = ((sudachiGame?.fileURL.startAccessingSecurityScopedResource()) != nil)
|
iscustom = ((sudachiGame?.fileURL.startAccessingSecurityScopedResource()) != nil)
|
||||||
|
|
||||||
DispatchQueue.global(qos: .userInitiated).async { [self] in
|
print(sudachiGame)
|
||||||
|
|
||||||
|
print("is outside url? \(iscustom ? "Yes" : "no")")
|
||||||
|
DispatchQueue.global(qos: .userInteractive).async { [self] in
|
||||||
if let sudachiGame = self.sudachiGame {
|
if let sudachiGame = self.sudachiGame {
|
||||||
|
|
||||||
if sudachiGame.fileURL == URL(string: "BootMii") {
|
if sudachiGame.fileURL == URL(string: "BootMii") {
|
||||||
@ -61,12 +64,7 @@ class SudachiEmulationViewModel: ObservableObject {
|
|||||||
|
|
||||||
private func step() {
|
private func step() {
|
||||||
while true {
|
while true {
|
||||||
if !isPaused {
|
sudachi.step()
|
||||||
sudachi.step()
|
|
||||||
} else {
|
|
||||||
print("pased")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ struct SudachiEmulationView: View {
|
|||||||
@State private var timer: Timer?
|
@State private var timer: Timer?
|
||||||
@Environment(\.scenePhase) var scenePhase
|
@Environment(\.scenePhase) var scenePhase
|
||||||
@AppStorage("isairplay") private var isairplay: Bool = true
|
@AppStorage("isairplay") private var isairplay: Bool = true
|
||||||
|
@AppStorage("HideMenuButton") private var HideMenuButton: Bool = true
|
||||||
let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
|
||||||
@ -43,70 +44,71 @@ struct SudachiEmulationView: View {
|
|||||||
|
|
||||||
|
|
||||||
ControllerView()
|
ControllerView()
|
||||||
|
if !HideMenuButton {
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Menu {
|
Menu {
|
||||||
Button {
|
Button {
|
||||||
if let metalView = mtkview {
|
if let metalView = mtkview {
|
||||||
print("button pressed")
|
print("button pressed")
|
||||||
|
|
||||||
let lastDrawableDisplayed = metalView.currentDrawable?.texture
|
|
||||||
|
|
||||||
if let imageRef = lastDrawableDisplayed?.toImage() {
|
|
||||||
let uiImage: UIImage = UIImage.init(cgImage: imageRef)
|
|
||||||
|
|
||||||
if let pngData = uiImage.pngData() {
|
let lastDrawableDisplayed = metalView.currentDrawable?.texture
|
||||||
// Define the path to save the PNG file
|
|
||||||
if let game = self.game {
|
if let imageRef = lastDrawableDisplayed?.toImage() {
|
||||||
let fileURL = documentsDir.appendingPathComponent("screenshots/\(game.title)-(\(Date())).png")
|
let uiImage: UIImage = UIImage.init(cgImage: imageRef)
|
||||||
print(Date())
|
|
||||||
do {
|
if let pngData = uiImage.pngData() {
|
||||||
// Write the PNG data to the file
|
// Define the path to save the PNG file
|
||||||
try pngData.write(to: fileURL)
|
if let game = self.game {
|
||||||
print("Image saved to: \(fileURL.path)")
|
let fileURL = documentsDir.appendingPathComponent("screenshots/\(game.title)-(\(Date())).png")
|
||||||
} catch {
|
print(Date())
|
||||||
print("Error saving PNG: \(error)")
|
do {
|
||||||
|
// Write the PNG data to the file
|
||||||
|
try pngData.write(to: fileURL)
|
||||||
|
print("Image saved to: \(fileURL.path)")
|
||||||
|
} catch {
|
||||||
|
print("Error saving PNG: \(error)")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let fileURL = documentsDir.appendingPathComponent("screenshots/Home_Menu-(\(Date())).png")
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Write the PNG data to the file
|
||||||
|
try pngData.write(to: fileURL)
|
||||||
|
print("Image saved to: \(fileURL.path)")
|
||||||
|
} catch {
|
||||||
|
print("Error saving PNG: \(error)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let fileURL = documentsDir.appendingPathComponent("screenshots/Home_Menu-(\(Date())).png")
|
print("Failed to convert UIImage to PNG data")
|
||||||
|
|
||||||
do {
|
|
||||||
// Write the PNG data to the file
|
|
||||||
try pngData.write(to: fileURL)
|
|
||||||
print("Image saved to: \(fileURL.path)")
|
|
||||||
} catch {
|
|
||||||
print("Error saving PNG: \(error)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
print("Failed to convert UIImage to PNG data")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} label: {
|
||||||
|
Text("Take Screenshot")
|
||||||
|
.font(.title)
|
||||||
|
.padding()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
viewModel.customButtonTapped()
|
||||||
|
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
|
} label: {
|
||||||
|
Text("Exit (Unstable)")
|
||||||
|
}
|
||||||
|
|
||||||
} label: {
|
} label: {
|
||||||
Text("Take Screenshot")
|
Image(systemName: "ellipsis.circle.fill")
|
||||||
.font(.title)
|
.resizable()
|
||||||
.padding()
|
.frame(width: 45, height: 45)
|
||||||
|
.foregroundColor(Color.gray)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
|
||||||
viewModel.customButtonTapped()
|
|
||||||
|
|
||||||
presentationMode.wrappedValue.dismiss()
|
|
||||||
} label: {
|
|
||||||
Text("Exit (Unstable)")
|
|
||||||
}
|
|
||||||
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "ellipsis.circle.fill")
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 45, height: 45)
|
|
||||||
.foregroundColor(Color.gray)
|
|
||||||
}
|
}
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.overlay(
|
.overlay(
|
||||||
|
@ -12,11 +12,28 @@ import Sudachi
|
|||||||
struct BottomMenuView: View {
|
struct BottomMenuView: View {
|
||||||
@Binding var core: Core
|
@Binding var core: Core
|
||||||
@State var isImporting: Bool = false
|
@State var isImporting: Bool = false
|
||||||
|
@State var isSelecting: Bool = false
|
||||||
|
|
||||||
|
@State var urlgame: PomeloGame?
|
||||||
|
|
||||||
|
@State var startgame = false
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 40) {
|
HStack(spacing: 40) {
|
||||||
|
|
||||||
|
NavigationLink(
|
||||||
|
destination: urlgame != nil ? AnyView(SudachiEmulationView(game: urlgame!)) : AnyView(EmptyView()),
|
||||||
|
// destination: SudachiEmulationView(game: urlgame),
|
||||||
|
isActive: $startgame,
|
||||||
|
label: {
|
||||||
|
EmptyView() // Keeps the link hidden
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.hidden()
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
if let url = URL(string: "messages://") { // Replace appScheme with the actual URL scheme of the app
|
if let url = URL(string: "messages://") {
|
||||||
if UIApplication.shared.canOpenURL(url) {
|
if UIApplication.shared.canOpenURL(url) {
|
||||||
UIApplication.shared.open(url, options: [:]) { (success) in
|
UIApplication.shared.open(url, options: [:]) { (success) in
|
||||||
if success {
|
if success {
|
||||||
@ -51,8 +68,19 @@ struct BottomMenuView: View {
|
|||||||
.foregroundColor(Color.init(uiColor: .darkGray))
|
.foregroundColor(Color.init(uiColor: .darkGray))
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Menu {
|
||||||
isImporting = true
|
Button {
|
||||||
|
isImporting = true
|
||||||
|
} label: {
|
||||||
|
Text("Import Files")
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
isSelecting = true
|
||||||
|
isImporting.toggle()
|
||||||
|
} label: {
|
||||||
|
Text("Open Game (without importing)")
|
||||||
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Circle()
|
Circle()
|
||||||
.overlay {
|
.overlay {
|
||||||
@ -63,6 +91,7 @@ struct BottomMenuView: View {
|
|||||||
.frame(width: 50, height: 50)
|
.frame(width: 50, height: 50)
|
||||||
.foregroundColor(Color.init(uiColor: .darkGray))
|
.foregroundColor(Color.init(uiColor: .darkGray))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NavigationLink(destination: SettingsView(core: core)) {
|
NavigationLink(destination: SettingsView(core: core)) {
|
||||||
@ -89,52 +118,86 @@ struct BottomMenuView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.bottom, 20)
|
.padding(.bottom, 20)
|
||||||
|
|
||||||
.fileImporter(isPresented: $isImporting, allowedContentTypes: [.zip, .item]) { result in
|
.fileImporter(isPresented: $isImporting, allowedContentTypes: [.zip, .item]) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let url):
|
case .success(let url):
|
||||||
let directory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
if isSelecting {
|
||||||
if url.lastPathComponent.hasSuffix(".zip") {
|
startGame(url: url)
|
||||||
core.AddFirmware(at: url)
|
isSelecting = false
|
||||||
|
} else {
|
||||||
|
addGame(url: url)
|
||||||
}
|
}
|
||||||
|
|
||||||
if core.supportedFileTypes.contains(url.pathExtension.lowercased()) {
|
|
||||||
let fileManager = FileManager.default
|
|
||||||
let has = url.startAccessingSecurityScopedResource()
|
|
||||||
do {
|
|
||||||
// Move the file
|
|
||||||
try fileManager.copyItem(at: url, to: directory.appendingPathComponent("roms").appendingPathComponent(url.lastPathComponent))
|
|
||||||
} catch {
|
|
||||||
print("Error moving file: \(error.localizedDescription)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if has {
|
|
||||||
url.stopAccessingSecurityScopedResource()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if url.lastPathComponent.hasSuffix(".keys") {
|
|
||||||
let fileManager = FileManager.default
|
|
||||||
let has = url.startAccessingSecurityScopedResource()
|
|
||||||
do {
|
|
||||||
// Move the file
|
|
||||||
try fileManager.copyItem(at: url, to: directory.appendingPathComponent("keys").appendingPathComponent(url.lastPathComponent))
|
|
||||||
} catch {
|
|
||||||
print("Error moving file: \(error.localizedDescription)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if has {
|
|
||||||
url.stopAccessingSecurityScopedResource()
|
|
||||||
}
|
|
||||||
|
|
||||||
let sudachi = Sudachi.shared
|
|
||||||
|
|
||||||
sudachi.refreshKeys()
|
|
||||||
}
|
|
||||||
|
|
||||||
core.refreshcore(core: &core)
|
|
||||||
case .failure(let err):
|
case .failure(let err):
|
||||||
print(err)
|
print(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startGame(url: URL) {
|
||||||
|
if core.supportedFileTypes.contains(url.pathExtension.lowercased()) {
|
||||||
|
let bool = url.startAccessingSecurityScopedResource()
|
||||||
|
|
||||||
|
defer {
|
||||||
|
if bool {
|
||||||
|
url.stopAccessingSecurityScopedResource()
|
||||||
|
|
||||||
|
startgame = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let sudachi = Sudachi.shared
|
||||||
|
|
||||||
|
let info = sudachi.information(for: url)
|
||||||
|
|
||||||
|
let game = PomeloGame(programid: Int(info.programID), ishomebrew: info.isHomebrew, developer: info.developer, fileURL: url, imageData: info.iconData, title: info.title)
|
||||||
|
|
||||||
|
|
||||||
|
urlgame = game
|
||||||
|
print(game)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addGame(url: URL) {
|
||||||
|
let directory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||||
|
if url.lastPathComponent.hasSuffix(".zip") {
|
||||||
|
core.AddFirmware(at: url)
|
||||||
|
}
|
||||||
|
|
||||||
|
if core.supportedFileTypes.contains(url.pathExtension.lowercased()) {
|
||||||
|
let fileManager = FileManager.default
|
||||||
|
let has = url.startAccessingSecurityScopedResource()
|
||||||
|
do {
|
||||||
|
// Move the file
|
||||||
|
try fileManager.copyItem(at: url, to: directory.appendingPathComponent("roms").appendingPathComponent(url.lastPathComponent))
|
||||||
|
} catch {
|
||||||
|
print("Error moving file: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if has {
|
||||||
|
url.stopAccessingSecurityScopedResource()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if url.lastPathComponent.hasSuffix(".keys") {
|
||||||
|
let fileManager = FileManager.default
|
||||||
|
let has = url.startAccessingSecurityScopedResource()
|
||||||
|
do {
|
||||||
|
// Move the file
|
||||||
|
try fileManager.copyItem(at: url, to: directory.appendingPathComponent("keys").appendingPathComponent(url.lastPathComponent))
|
||||||
|
} catch {
|
||||||
|
print("Error moving file: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if has {
|
||||||
|
url.stopAccessingSecurityScopedResource()
|
||||||
|
}
|
||||||
|
|
||||||
|
let sudachi = Sudachi.shared
|
||||||
|
|
||||||
|
sudachi.refreshKeys()
|
||||||
|
}
|
||||||
|
|
||||||
|
core.refreshcore(core: &core)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,7 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.developer.applesignin</key>
|
|
||||||
<array>
|
|
||||||
<string>Default</string>
|
|
||||||
</array>
|
|
||||||
<key>com.apple.developer.kernel.extended-virtual-addressing</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.developer.kernel.increased-debugging-memory-limit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.developer.kernel.increased-memory-limit</key>
|
<key>com.apple.developer.kernel.increased-memory-limit</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.files.user-selected.read-only</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.network.client</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -2,21 +2,7 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.developer.applesignin</key>
|
|
||||||
<array>
|
|
||||||
<string>Default</string>
|
|
||||||
</array>
|
|
||||||
<key>com.apple.developer.kernel.extended-virtual-addressing</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.developer.kernel.increased-debugging-memory-limit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.developer.kernel.increased-memory-limit</key>
|
<key>com.apple.developer.kernel.increased-memory-limit</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.files.user-selected.read-only</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.network.client</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -58,6 +58,7 @@ struct AdvancedSettingsView: View {
|
|||||||
.padding(.bottom)
|
.padding(.bottom)
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
.foregroundColor(.gray)
|
.foregroundColor(.gray)
|
||||||
|
|
||||||
if canShowMetalHUD {// (Int(UIDevice.current.systemVersion) ?? 0 >= 16) || canShowMetalHUD {
|
if canShowMetalHUD {// (Int(UIDevice.current.systemVersion) ?? 0 >= 16) || canShowMetalHUD {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(Color(uiColor: UIColor.secondarySystemBackground))
|
.fill(Color(uiColor: UIColor.secondarySystemBackground))
|
||||||
|
@ -119,7 +119,7 @@ struct SettingsView: View {
|
|||||||
.frame(width: .infinity, height: 50) // Set the desired dimensions
|
.frame(width: .infinity, height: 50) // Set the desired dimensions
|
||||||
.overlay() {
|
.overlay() {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Advanced Settings")
|
Text("App Settings")
|
||||||
.foregroundColor(.primary)
|
.foregroundColor(.primary)
|
||||||
.padding()
|
.padding()
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -128,31 +128,6 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
if isshown {
|
|
||||||
Rectangle()
|
|
||||||
.fill(Color(uiColor: UIColor.secondarySystemBackground)) // Set the fill color (optional)
|
|
||||||
.cornerRadius(10) // Apply rounded corners
|
|
||||||
.frame(width: .infinity, height: 50) // Set the desired dimensions
|
|
||||||
.overlay() {
|
|
||||||
HStack(alignment: .center) {
|
|
||||||
SignInApple()
|
|
||||||
.frame(width: 200, height: 50)
|
|
||||||
.foregroundColor(Color(uiColor: UIColor.secondarySystemBackground))
|
|
||||||
}
|
|
||||||
.onAppear {
|
|
||||||
ASAuthorizationAppleIDProvider().getCredentialState(forUserID: deviceOwnerID ?? "0") { state, error in
|
|
||||||
if state != .authorized {
|
|
||||||
isshown = true
|
|
||||||
UserDefaults.standard.set(nil, forKey: "deviceOwnerName")
|
|
||||||
UserDefaults.standard.set(nil, forKey: "deviceOwnerID")
|
|
||||||
} else {
|
|
||||||
isshown = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NavigationLink(destination: AppIconSwitcherView()) {
|
NavigationLink(destination: AppIconSwitcherView()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user