Path: blob/a-new-beginning/Folium-iOS/Classes/Games/Games.swift
2 views
//
// BaseGame.swift
// Folium-iOS
//
// Created by Jarrod Norwell on 10/3/2026.
//
import Cytrus
import CombinedCores
import CoreGraphics
import Foundation
import UIKit
class CodableHashableSendable : Codable, Hashable, @unchecked Sendable {
var id: UUID = UUID()
static func == (lhs: CodableHashableSendable, rhs: CodableHashableSendable) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
class BaseGame : Codable, Comparable, Hashable, @unchecked Sendable {
var id: UUID = UUID()
let name: String
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func == (lhs: BaseGame, rhs: BaseGame) -> Bool {
lhs.id == rhs.id
}
static func < (lhs: BaseGame, rhs: BaseGame) -> Bool {
lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending
}
init(details: GameDetails) {
name = details.name
}
func getCore() -> Core? {
switch self {
case is NewCherryGame: .cherry
case is NewCytrusGame: .cytrus
case is NewGrapeGame: .grape
case is NewGuavaGame: .guava
case is NewKiwiGame: .kiwi
case is NewMandarineGame: .mandarine
case is NewMangoGame: .mango
case is NewPlumGame: .plum
case is NewTomatoGame: .tomato
default: nil
}
}
func asGame<T>() -> T? {
self as? T
}
}
class NewCherryGame : BaseGame, @unchecked Sendable {
let core: Core
let details: GameDetails
let skins: [Skin]
init(cartridge: URL, skinManager: SkinManager) {
core = .cherry
details = GameDetails(cartridge: cartridge)
skins = skinManager.skins(for: .cherry)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class NewCytrusGame : BaseGame, @unchecked Sendable {
// TODO: rewrite this
class Extras : CodableHashableSendable, @unchecked Sendable {
var cheats: [CytrusCheat] = []
var saveStates: [CytrusSaveState] = []
var identifier: UInt64? = nil
var cytrus: Cytrus
var cheatsManager: CytrusCheatsManager
init(cytrus: Cytrus, identifier: UInt64? = nil, _ error: inout NSError?) {
self.cytrus = cytrus
self.identifier = identifier
self.cheatsManager = .init(with: identifier ?? 999)
self.cheatsManager.load()
self.cheats = self.cheatsManager.cheats()
for element in cytrus.savesStates(for: identifier ?? 999) {
switch element {
case let saveState as CytrusSaveState:
self.saveStates.append(saveState)
case let nsError as NSError:
error = nsError
default:
break
}
}
super.init()
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
func toggle(_ cheat: CytrusCheat, _ index: Int = -1) {
cheatsManager.toggle(cheat: cheat)
guard index >= 0 else {
return
}
cheatsManager.update(cheat: cheat, at: index)
cheatsManager.save()
}
func update() {
cheatsManager.load()
cheats = cheatsManager.cheats()
saveStates.removeAll()
for element in cytrus.savesStates(for: identifier ?? 999) {
switch element {
case let saveState as CytrusSaveState:
saveStates.append(saveState)
default:
break
}
}
}
}
// TODO: rewrite this
class Information : CodableHashableSendable, @unchecked Sendable {
var identifier: UInt64? = nil
var kernelMemoryMode: CytrusKernelMemoryMode? = nil
var new3DSKernelMemoryMode: CytrusNew3DSKernelMemoryMode? = nil
var publisher: String? = nil
var regions: String? = nil
init(from information: CytrusGameInformation) {
self.identifier = information.identifier
self.kernelMemoryMode = information.kernelMemoryMode
self.new3DSKernelMemoryMode = information.new3DSKernelMemoryMode
self.publisher = information.publisher
self.regions = information.regions
super.init()
}
init(identifier: UInt64? = nil, kernelMemoryMode: CytrusKernelMemoryMode? = nil,
new3DSKernelMemoryMode: CytrusNew3DSKernelMemoryMode? = nil, publisher: String? = nil, regions: String? = nil) {
self.identifier = identifier
self.kernelMemoryMode = kernelMemoryMode
self.new3DSKernelMemoryMode = new3DSKernelMemoryMode
self.publisher = publisher
self.regions = regions
super.init()
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
let core: Core
var details: GameDetails
var extras: Extras
var icon: Data?
var information: Information
let skins: [Skin]
init(cartridge: URL, cytrusCore: Cytrus, skinManager: SkinManager) {
core = .cytrus
details = GameDetails(cartridge: cartridge)
var error: NSError?
extras = Extras(cytrus: cytrusCore, identifier: nil, &error)
information = Information()
skins = skinManager.skins(for: .cytrus)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class NewGrapeGame : BaseGame, @unchecked Sendable {
let core: Core
let details: GameDetails
var icon: CGImage?
let skins: [Skin]
init(cartridge: URL, grapeCore: CombinedCores.GrapeCore, skinManager: SkinManager) {
core = .grape
details = GameDetails(cartridge: cartridge)
skins = skinManager.skins(for: .grape)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class NewGuavaGame : BaseGame, @unchecked Sendable {
let core: Core
let details: GameDetails
let skins: [Skin]
init(cartridge: URL, guavaCore: CombinedCores.GuavaCore, skinManager: SkinManager) {
core = .guava
details = GameDetails(cartridge: cartridge)
skins = skinManager.skins(for: .guava)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class NewKiwiGame : BaseGame, @unchecked Sendable {
let core: Core
var details: GameDetails
let skins: [Skin]
init(cartridge: URL, kiwiCore: CombinedCores.KiwiCore, skinManager: SkinManager) {
core = .kiwi
details = GameDetails(cartridge: cartridge)
skins = skinManager.skins(for: .kiwi)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class NewMandarineGame : BaseGame, @unchecked Sendable {
let core: Core
let details: GameDetails
var icon: UIImage?
let skins: [Skin]
init(cartridge: URL, mandarineCore: CombinedCores.MandarineCore, skinManager: SkinManager) {
core = .mandarine
details = GameDetails(cartridge: cartridge)
skins = skinManager.skins(for: .mandarine)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class NewMangoGame : BaseGame, @unchecked Sendable {
let core: Core
let details: GameDetails
var icon: UIImage?
let skins: [Skin]
init(cartridge: URL, mangoCore: CombinedCores.MangoCore, skinManager: SkinManager) {
core = .mango
details = GameDetails(cartridge: cartridge)
skins = skinManager.skins(for: .mango)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class NewPlumGame : BaseGame, @unchecked Sendable {
let core: Core
let details: GameDetails
let skins: [Skin]
init(cartridge: URL, skinManager: SkinManager) {
core = .plum
details = GameDetails(cartridge: cartridge)
skins = skinManager.skins(for: .plum)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class NewTomatoGame : BaseGame, @unchecked Sendable {
let core: Core
let details: GameDetails
var icon: UIImage?
let skins: [Skin]
init(cartridge: URL, tomatoCore: CombinedCores.TomatoCore, skinManager: SkinManager) {
core = .tomato
details = GameDetails(cartridge: cartridge)
skins = skinManager.skins(for: .tomato)
super.init(details: details)
}
required init(from decoder: any Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}