Skip to content

Instantly share code, notes, and snippets.

@jarrodnorwell
Created January 20, 2024 11:16
Show Gist options
  • Save jarrodnorwell/9b81cd16831fa4da9b1bdf8c20c2fd8b to your computer and use it in GitHub Desktop.
Save jarrodnorwell/9b81cd16831fa4da9b1bdf8c20c2fd8b to your computer and use it in GitHub Desktop.
Library manager for Folium... is this messy? Maybe. Does it work? Yes.
import Foundation
struct Library {
struct Core {
enum Name : String {
case kiwi = "Kiwi", limon = "Limón", sudachi = "Sudachi"
}
class GameBase {}
class LimonGame : GameBase, Codable, Comparable {
let system: Bool
let publisher, regions, title: String
init(system: Bool, publisher: String, regions: String, title: String) {
self.system = system
self.publisher = publisher
self.regions = regions
self.title = title
}
static func < (lhs: Library.Core.LimonGame, rhs: Library.Core.LimonGame) -> Bool {
lhs.title < rhs.title
}
static func == (lhs: Library.Core.LimonGame, rhs: Library.Core.LimonGame) -> Bool {
lhs.title == rhs.title
}
}
class SudachiGame : GameBase, Codable, Comparable {
let developer: String
let iconData: Data
let isHomebrew: Bool
let title, version: String
init(developer: String, iconData: Data, isHomebrew: Bool, title: String, version: String) {
self.developer = developer
self.iconData = iconData
self.isHomebrew = isHomebrew
self.title = title
self.version = version
}
static func < (lhs: Library.Core.SudachiGame, rhs: Library.Core.SudachiGame) -> Bool {
lhs.title < rhs.title
}
static func == (lhs: Library.Core.SudachiGame, rhs: Library.Core.SudachiGame) -> Bool {
lhs.title == rhs.title
}
}
let name: Name
let roms: [GameBase]
}
let cores: [Core]
}
enum LibraryManagerError : Error {
case invalidEnumerator, invalidURL
}
class LibraryManager {
static let shared = LibraryManager()
func configureDocumentsDirectory() throws {
let directories = [
"Kiwi" : [
"roms"
],
"Limón" : [
"config",
"cache",
"sdmc",
"nand",
"sysdata",
"log",
"cheats",
"external_dlls",
"shaders",
"dump",
"load",
"shaders",
"states",
"roms"
],
"Sudachi" : [
"amiibo",
"cache",
"config",
"crash_dumps",
"dump",
"keys",
"load",
"log",
"nand",
"play_time",
"screenshots",
"sdmc",
"shader",
"tas",
"icons",
"roms"
]
]
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
try directories.forEach { directory, subdirectories in
let coreDirectory = documentsDirectory.appendingPathComponent(directory, conformingTo: .folder)
if !FileManager.default.fileExists(atPath: coreDirectory.path) {
try FileManager.default.createDirectory(at: coreDirectory, withIntermediateDirectories: false)
try subdirectories.forEach { directory in
let coreSubdirectory = coreDirectory.appendingPathComponent(directory, conformingTo: .folder)
if !FileManager.default.fileExists(atPath: coreSubdirectory.path) {
try FileManager.default.createDirectory(at: coreSubdirectory, withIntermediateDirectories: false)
}
}
} else {
try subdirectories.forEach { directory in
let coreSubdirectory = coreDirectory.appendingPathComponent(directory, conformingTo: .folder)
if !FileManager.default.fileExists(atPath: coreSubdirectory.path) {
try FileManager.default.createDirectory(at: coreSubdirectory, withIntermediateDirectories: false)
}
}
}
}
}
func library() throws -> Library {
func romsDirectoryCrawler(for coreName: Library.Core.Name) throws -> [URL] {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
guard let enumerator = FileManager.default.enumerator(at: documentsDirectory.appendingPathComponent(coreName.rawValue, conformingTo: .folder)
.appendingPathComponent("roms", conformingTo: .folder), includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else {
throw LibraryManagerError.invalidEnumerator
}
var urls: [URL] = []
try enumerator.forEach { element in
switch element {
case let url as URL:
let attributes = try url.resourceValues(forKeys: [.isRegularFileKey])
if let isRegularFile = attributes.isRegularFile, isRegularFile {
switch coreName {
case .kiwi:
break
case .limon:
if url.pathExtension == "3ds" || url.pathExtension == "app" || url.pathExtension == "cci" || url.pathExtension == "cxi" {
urls.append(url)
}
case .sudachi:
if url.pathExtension == "nsp" || url.pathExtension == "xci" {
urls.append(url)
}
}
}
default:
break
}
}
return urls
}
func roms(from urls: [URL], for coreName: Library.Core.Name) -> [Library.Core.GameBase] {
switch coreName {
case .kiwi:
urls.reduce(into: [Library.Core.LimonGame]()) { partialResult, element in
}
case .limon:
urls.reduce(into: [Library.Core.LimonGame]()) { partialResult, element in
// let information = Limon.shared().gameInformation.information(for: element)
// partialResult.append(.init(system: false, publisher: information.publisher, regions: information.regions, title: information.title))
}
case .sudachi:
urls.reduce(into: [Library.Core.SudachiGame]()) { partialResult, element in
let information = Sudachi.shared().gameInformation.information(for: element)
partialResult.append(.init(developer: information.developer, iconData: information.iconData,
isHomebrew: information.isHomebrew, title: information.title, version: information.version))
}
}
}
return .init(cores: [
.init(name: .kiwi, roms: roms(from: try romsDirectoryCrawler(for: .kiwi), for: .kiwi)),
.init(name: .limon, roms: roms(from: try romsDirectoryCrawler(for: .limon), for: .limon)),
.init(name: .sudachi, roms: roms(from: try romsDirectoryCrawler(for: .sudachi), for: .sudachi))
])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment