Skip to content

Commit

Permalink
Merge branch 'develop' into feature/game-controller-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
pabloarista authored Dec 29, 2024
2 parents 1149fee + bf26fe2 commit 2e14d63
Show file tree
Hide file tree
Showing 18 changed files with 588 additions and 473 deletions.
2 changes: 1 addition & 1 deletion Cores/CrabEMU
2 changes: 1 addition & 1 deletion Cores/VisualBoyAdvance-M/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let package = Package(
.tvOS(.v16),
.watchOS(.v9),
.macOS(.v11),
.macCatalyst(.v15),
.macCatalyst(.v17),
.visionOS(.v1)
],
products: [
Expand Down
12 changes: 6 additions & 6 deletions Cores/emuThree/PVEmuThree.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,11 @@
B318E2702CAA86BD00D0E599 /* CorePlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = B318E26F2CAA86BD00D0E599 /* CorePlist.swift */; };
B318E2722CAA871B00D0E599 /* CorePlist-Generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = B318E2712CAA871B00D0E599 /* CorePlist-Generated.swift */; };
B33350262078619C0036A448 /* Core.plist in Resources */ = {isa = PBXBuildFile; fileRef = B3C7622720783510009950E4 /* Core.plist */; };
B351E7BA2CBE067E0000E087 /* libavcodec.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7B92CBE067E0000E087 /* libavcodec.xcframework */; };
B351E7BE2CBE06C00000E087 /* libavformat.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7BD2CBE06C00000E087 /* libavformat.xcframework */; };
B351E7C12CBE06C80000E087 /* libavutil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7C02CBE06C80000E087 /* libavutil.xcframework */; };
B351E7C42CBE06CE0000E087 /* libswresample.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7C32CBE06CE0000E087 /* libswresample.xcframework */; };
B351E7C72CBE06E30000E087 /* libswscale.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7C62CBE06E20000E087 /* libswscale.xcframework */; };
B351E7BA2CBE067E0000E087 /* libavcodec.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7B92CBE067E0000E087 /* libavcodec.xcframework */; platformFilter = ios; };
B351E7BE2CBE06C00000E087 /* libavformat.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7BD2CBE06C00000E087 /* libavformat.xcframework */; platformFilter = ios; };
B351E7C12CBE06C80000E087 /* libavutil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7C02CBE06C80000E087 /* libavutil.xcframework */; platformFilter = ios; };
B351E7C42CBE06CE0000E087 /* libswresample.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7C32CBE06CE0000E087 /* libswresample.xcframework */; platformFilter = ios; };
B351E7C72CBE06E30000E087 /* libswscale.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = B351E7C62CBE06E20000E087 /* libswscale.xcframework */; platformFilter = ios; };
B35E6BF2207CD2680040709A /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B35E6BF1207CD2670040709A /* AudioToolbox.framework */; };
B35E6BF5207CD2740040709A /* CoreAudioKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B35E6BF3207CD2730040709A /* CoreAudioKit.framework */; platformFilters = (ios, maccatalyst, macos, watchos, ); };
B35E6BF6207CD2740040709A /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B35E6BF4207CD2740040709A /* CoreAudio.framework */; };
Expand All @@ -650,7 +650,7 @@
B37CDBAC2CAA6A950026E901 /* PVCoreObjCBridge in Frameworks */ = {isa = PBXBuildFile; productRef = B37CDBAB2CAA6A950026E901 /* PVCoreObjCBridge */; };
B37CDBAF2CAA6AF90026E901 /* PVPlists in Frameworks */ = {isa = PBXBuildFile; productRef = B37CDBAE2CAA6AF90026E901 /* PVPlists */; };
B3C7621F2078325C009950E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3C7621E2078325C009950E4 /* Foundation.framework */; };
B3CC2E232CBC245F00D90EB1 /* MoltenVK in Frameworks */ = {isa = PBXBuildFile; productRef = B3CC2E222CBC245F00D90EB1 /* MoltenVK */; };
B3CC2E232CBC245F00D90EB1 /* MoltenVK in Frameworks */ = {isa = PBXBuildFile; platformFilter = ios; productRef = B3CC2E222CBC245F00D90EB1 /* MoltenVK */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down
16 changes: 12 additions & 4 deletions Cores/emuThree/PVEmuThreeCore/Core/PVEmuThreeCoreBridge+Saves.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ -(BOOL)supportsSaveStates {

- (BOOL)saveStateToFileAtPath:(NSString *)fileName {
if( _isInitialized)
[CitraWrapper.sharedInstance requestSave:fileName];
@autoreleasepool {
[CitraWrapper.sharedInstance requestSave:fileName];
}
return true;
}

- (BOOL)saveStateToFileAtPath:(NSString *)fileName completionHandler:(void (^)(NSError *))block {
bool success=false;
if( _isInitialized) {
[CitraWrapper.sharedInstance requestSave:fileName];
@autoreleasepool {
[CitraWrapper.sharedInstance requestSave:fileName];
}
success=true;
}
if (success) {
Expand All @@ -48,13 +52,17 @@ - (BOOL)loadStateFromFileAtPath:(NSString *)fileName {
autoLoadStatefileName = fileName;
[NSThread detachNewThreadSelector:@selector(autoloadWaitThread) toTarget:self withObject:nil];
} else {
[CitraWrapper.sharedInstance requestLoad:fileName];
@autoreleasepool {
[CitraWrapper.sharedInstance requestLoad:fileName];
}
}
return true;
}

- (BOOL)loadStateFromFileAtPath:(NSString *)fileName completionHandler:(void (^)(NSError *))block {
[CitraWrapper.sharedInstance requestLoad:fileName];
@autoreleasepool {
[CitraWrapper.sharedInstance requestLoad:fileName];
}
bool success=true;

if (success) {
Expand Down
44 changes: 35 additions & 9 deletions PVFeatureFlags/Sources/PVFeatureFlags/PVFeatureFlags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,26 @@ public struct FeatureFlagsConfiguration: Codable, Sendable {
/// Dictionary of cached feature states
@Published private var featureStates: [String: Bool] = [:]

/// Dictionary to store debug overrides - made internal for testing
public var debugOverrides: [String: Bool] = [:]
/// Dictionary to store debug overrides - persisted in UserDefaults
public var debugOverrides: [String: Bool] {
get {
UserDefaults.standard.dictionary(forKey: "PVFeatureFlagsDebugOverrides") as? [String: Bool] ?? [:]
}
set {
UserDefaults.standard.set(newValue, forKey: "PVFeatureFlagsDebugOverrides")
objectWillChange.send()
}
}

/// Dictionary to store remote feature flags
private var remoteFlags: [String: Bool] = [:]

private init() {
self.featureFlags = PVFeatureFlags()
// Load any persisted debug overrides
if let savedOverrides = UserDefaults.standard.dictionary(forKey: "PVFeatureFlagsDebugOverrides") as? [String: Bool] {
print("Loaded debug overrides from UserDefaults: \(savedOverrides)")
}
}

/// Initialize with custom parameters for testing
Expand Down Expand Up @@ -302,13 +314,27 @@ public struct FeatureFlagsConfiguration: Codable, Sendable {
return enabled
}

/// Whether the romPathMigrator feature is enabled
public var romPathMigrator: Bool {
/// Check debug override first
if let override = debugOverrides["romPathMigrator"] {
print("Debug override active for romPathMigrator: \(override)")
return override
}

/// Fall back to main feature flags system
let enabled = featureFlags.isEnabled("romPathMigrator")
print("No debug override, using feature flags system value for romPathMigrator: \(enabled)")
return enabled
}

/// Set a debug override for a feature flag
public func setDebugOverride(feature: String, enabled: Bool) {
print("Setting debug override for \(feature) to: \(enabled)")
debugOverrides[feature] = enabled
var currentOverrides = debugOverrides
currentOverrides[feature] = enabled
debugOverrides = currentOverrides
print("Current debug overrides: \(debugOverrides)")
// Notify observers that the value has changed
objectWillChange.send()
// Update cached states
updateFeatureStates()
}
Expand Down Expand Up @@ -345,16 +371,16 @@ public struct FeatureFlagsConfiguration: Codable, Sendable {
/// Clear all debug overrides
public func clearDebugOverrides() {
print("Clearing all debug overrides")
debugOverrides.removeAll()
objectWillChange.send()
debugOverrides = [:]
updateFeatureStates()
}

/// Clear specific debug override
public func clearDebugOverride(for feature: String) {
print("Clearing debug override for \(feature)")
debugOverrides.removeValue(forKey: feature)
objectWillChange.send()
var currentOverrides = debugOverrides
currentOverrides.removeValue(forKey: feature)
debugOverrides = currentOverrides
updateFeatureStates()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ import PVFileSystem

/// Handles migration of ROM and BIOS files from old documents directory to new shared container directory
public final class ROMLocationMigrator {
private let fileManager = FileManager.default

private let fileManager: FileManager

public init(fileManager: FileManager = FileManager.default) {
self.fileManager = fileManager
}

/// Old paths that need migration
private var oldPaths: [(source: URL, destination: URL)] {
Expand Down
41 changes: 22 additions & 19 deletions PVLibrary/Sources/PVLibrary/Database/PVGameLibrary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import RealmSwift
import RxRealm
import PVLogging
import PVRealm
import PVFeatureFlags
@_exported public import PVSettings

public class PVGameLibrary<T> where T: DatabaseDriver {

public struct System {
public let identifier: String
public let manufacturer: String
Expand All @@ -25,24 +26,26 @@ public class PVGameLibrary<T> where T: DatabaseDriver {
public let unsupported: Bool
public let sortedGames: [T.GameType]
}

public let database: RomDatabase
public let databaseDriver: T
public let romMigrator: ROMLocationMigrator

public init(database: RomDatabase) {
public let romMigrator: ROMLocationMigrator
public init(database: RomDatabase, migrator: ROMLocationMigrator = .init()) {
self.database = database
self.databaseDriver = .init(database: database)
self.romMigrator = ROMLocationMigrator()

self.romMigrator = migrator
// Kick off ROM migration
Task.detached {
do {
try await self.romMigrator.migrateIfNeeded()
try await self.romMigrator.fixOrphanedFiles()
ILOG("ROM migration completed successfully")
} catch {
ELOG("ROM migration failed: \(error.localizedDescription)")
Task {
if await PVFeatureFlagsManager.shared.romPathMigrator {
do {
try await self.romMigrator.migrateIfNeeded()
try await self.romMigrator.fixOrphanedFiles()
ILOG("ROM migration completed successfully")
} catch {
ELOG("ROM migration failed: \(error.localizedDescription)")
}
}
}
}
Expand All @@ -67,7 +70,7 @@ extension RealmSwift.LinkingObjects where Element: PVGame {
case .mostPlayed:
sortDescriptors.append(SortDescriptor(keyPath: #keyPath(PVGame.playCount), ascending: false))
}

sortDescriptors.append(SortDescriptor(keyPath: #keyPath(PVGame.title), ascending: true))
return sorted(by: sortDescriptors)
}
Expand All @@ -83,15 +86,15 @@ extension Array where Element == PVGameLibrary<RealmDatabaseDriver>.System {
return mc == .orderedAscending
}
}

switch sortOptions {
case .title:
return sorted(by: titleSort)
case .lastPlayed:
return sorted(by: { (s1, s2) -> Bool in
let l1 = s1.sortedGames.first?.lastPlayed
let l2 = s2.sortedGames.first?.lastPlayed

if let l1 = l1, let l2 = l2 {
return l1.compare(l2) == .orderedDescending
} else if l1 != nil {
Expand All @@ -106,7 +109,7 @@ extension Array where Element == PVGameLibrary<RealmDatabaseDriver>.System {
return sorted(by: { (s1, s2) -> Bool in
let l1 = s1.sortedGames.first?.importDate
let l2 = s2.sortedGames.first?.importDate

if let l1 = l1, let l2 = l2 {
return l1.compare(l2) == .orderedDescending
} else if l1 != nil {
Expand All @@ -121,7 +124,7 @@ extension Array where Element == PVGameLibrary<RealmDatabaseDriver>.System {
return sorted(by: { (s1, s2) -> Bool in
let l1 = s1.sortedGames.first?.playCount
let l2 = s2.sortedGames.first?.playCount

if let l1 = l1, let l2 = l2 {
return l1 < l2
} else if l1 != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,28 @@ public extension RomDatabase {
NSLog("Failed to hide game \(game.title)\n\(error.localizedDescription)")
}
}

func delete(bios: PVBIOS) throws {
guard let biosURL = bios.file?.url else {
ELOG("No path for BIOS")
throw RomDeletionError.relatedFiledDeletionError
}
if FileManager.default.fileExists(atPath: biosURL.path) {
do {
try FileManager.default.removeItem(at: biosURL)
ILOG("Deleted BIOS \(bios.expectedFilename)\n\(biosURL.path)")
// Remove the PVFile from the PVBios
let realm = try Realm()
let bios = bios.warmUp()
try realm.write {
bios.file = nil
}
} catch {
WLOG("Failed to delete BIOS \(bios.expectedFilename)\n\(error.localizedDescription)")
}
}
}

func delete(game: PVGame, deleteArtwork: Bool = false, deleteSaves: Bool = false) throws {
let romURL = PVEmulatorConfiguration.path(forGame: game)
if deleteArtwork, !game.customArtworkURL.isEmpty {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public class PVFile: Object, LocalFileProvider, Codable, DomainConvertibleType {
self.lastSizeCheck = Date()
}
}

public override static func ignoredProperties() -> [String] {
return ["sizeCache", "lastSizeCheck"]
}
Expand Down Expand Up @@ -125,18 +125,16 @@ public extension PVFile {
return nil
}

// Task {
guard let realm = self.realm else {
return nil
}
// Cache the MD5 only if we're not frozen
if !self.isFrozen, let realm = self.realm {
do {
try realm.write {
md5Cache = calculatedMD5
}
} catch {
ELOG("\(error)")
ELOG("Failed to cache MD5: \(error)")
}
// }
}

return calculatedMD5
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public extension ROMMetadataProvider {
.replacingOccurrences(of: "]", with: "\\]")
.replacingOccurrences(of: "*", with: "\\*") // Wildcards
.replacingOccurrences(of: "?", with: "\\?")
.replacingOccurrences(of: "#", with: "\\#")

return escapedLike
}
Expand Down
Loading

0 comments on commit 2e14d63

Please sign in to comment.