SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
iOS/GBROMManager.m
1 #import "GBROMManager.h"
2 #import <copyfile.h>
3 #import <sys/stat.h>
4
5 @implementation GBROMManager
6 {
7 NSString *_romFile;
8 NSMutableDictionary<NSString *,NSString *> *_cloudNameToFile;
9 bool _doneInitializing;
10 }
11
12 + (instancetype)sharedManager
13 {
14 static dispatch_once_t onceToken;
15 static GBROMManager *manager;
16 dispatch_once(&onceToken, ^{
17 manager = [[self alloc] init];
18 });
19 return manager;
20 }
21
22 - (instancetype)init
23 {
24 self = [super init];
25 if (!self) return nil;
26 self.currentROM = [[NSUserDefaults standardUserDefaults] stringForKey:@"GBLastROM"];
27 _doneInitializing = true;
28
29 // Pre 1.0.2 versions might have kept temp files in there incorrectly
30 if (![[NSUserDefaults standardUserDefaults] boolForKey:@"GBDeletedInbox"]) {
31 [[NSFileManager defaultManager] removeItemAtPath:[self.localRoot stringByAppendingPathComponent:@"Inbox"] error:nil];
32 [[NSUserDefaults standardUserDefaults] setBool:true forKey:@"GBDeletedInbox"];
33 }
34 return self;
35 }
36
37 - (NSArray<NSString *> *)forbiddenNames
38 {
39 return @[@"Inbox", @"Boot ROMs"];
40 }
41
42 - (void)setCurrentROM:(NSString *)currentROM
43 {
44 _romFile = nil;
45 if ([self.forbiddenNames containsObject:currentROM]) {
46 currentROM = nil;
47 }
48 _currentROM = currentROM;
49 bool foundROM = self.romFile;
50
51 if (currentROM && !foundROM) {
52 _currentROM = nil;
53 }
54
55 [[NSUserDefaults standardUserDefaults] setObject:_currentROM forKey:@"GBLastROM"];
56 if (_doneInitializing) {
57 [[NSNotificationCenter defaultCenter] postNotificationName:@"GBROMChanged" object:nil];
58 }
59 }
60
61 - (NSString *)romFileForDirectory:(NSString *)romDirectory
62 {
63 for (NSString *filename in [NSFileManager.defaultManager contentsOfDirectoryAtPath:romDirectory
64 error:nil]) {
65 if ([@[@"gb", @"gbc", @"isx"] containsObject:filename.pathExtension.lowercaseString]) {
66 return [romDirectory stringByAppendingPathComponent:filename];
67 }
68 }
69
70 return nil;
71 }
72
73 - (NSString *)romDirectoryForROM:(NSString *)romFile
74 {
75 if ([self.forbiddenNames containsObject:romFile]) {
76 return nil;
77 }
78
79 return [self.localRoot stringByAppendingPathComponent:romFile];
80 }
81
82 - (NSString *)romFile
83 {
84 if (_romFile) return _romFile;
85 if (!_currentROM) return nil;
86 return _romFile = [self romFileForDirectory:[self romDirectoryForROM:_currentROM]];
87 }
88
89 - (NSString *)romFileForROM:(NSString *)rom
90 {
91 if (rom == _currentROM) {
92 return self.romFile;
93 }
94
95 if ([self.forbiddenNames containsObject:rom]) {
96 return nil;
97 }
98
99 return [self romFileForDirectory:[self romDirectoryForROM:rom]];
100 }
101
102 - (NSString *)auxilaryFileForROM:(NSString *)rom withExtension:(NSString *)extension
103 {
104 return [[[self romFileForROM:rom] stringByDeletingPathExtension] stringByAppendingPathExtension:extension];
105 }
106
107 - (NSString *)batterySaveFileForROM:(NSString *)rom
108 {
109 return [self auxilaryFileForROM:rom withExtension:@"sav"];
110 }
111
112 - (NSString *)batterySaveFile
113 {
114 return [self batterySaveFileForROM:_currentROM];
115 }
116
117 - (NSString *)autosaveStateFileForROM:(NSString *)rom
118 {
119 return [self auxilaryFileForROM:rom withExtension:@"auto"];
120 }
121
122 - (NSString *)autosaveStateFile
123 {
124 return [self autosaveStateFileForROM:_currentROM];
125 }
126
127 - (NSString *)stateFile:(unsigned)index forROM:(NSString *)rom
128 {
129 return [self auxilaryFileForROM:rom withExtension:[NSString stringWithFormat:@"s%u", index]];
130 }
131
132 - (NSString *)stateFile:(unsigned)index
133 {
134 return [self stateFile:index forROM:_currentROM];
135 }
136
137
138 - (NSString *)cheatsFileForROM:(NSString *)rom
139 {
140 return [self auxilaryFileForROM:rom withExtension:@"cht"];
141 }
142
143 - (NSString *)cheatsFile
144 {
145 return [self cheatsFileForROM:_currentROM];
146 }
147
148 - (NSArray<NSString *> *)allROMs
149 {
150 NSMutableArray<NSString *> *ret = [NSMutableArray array];
151 NSString *root = self.localRoot;
152 for (NSString *romDirectory in [NSFileManager.defaultManager contentsOfDirectoryAtPath:root
153 error:nil]) {
154 if ([romDirectory hasPrefix:@"."] || [romDirectory isEqualToString:@"Inbox"]) continue;
155 if ([self romFileForDirectory:[root stringByAppendingPathComponent:romDirectory]]) {
156 [ret addObject:romDirectory];
157 }
158 }
159 return [ret sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
160 }
161
162 - (NSString *)makeNameUnique:(NSString *)name
163 {
164 if ([self.forbiddenNames containsObject:name]) {
165 name = @"Imported ROM";
166 }
167 NSString *root = self.localRoot;
168 if (![[NSFileManager defaultManager] fileExistsAtPath:[root stringByAppendingPathComponent:name]]) return name;
169
170 unsigned i = 2;
171 while (true) {
172 NSString *attempt = [name stringByAppendingFormat:@" %u", i];
173 if ([[NSFileManager defaultManager] fileExistsAtPath:[root stringByAppendingPathComponent:attempt]]) {
174 i++;
175 continue;
176 }
177 return attempt;
178 }
179 }
180
181 - (NSString *)importROM:(NSString *)romFile keepOriginal:(bool)keep
182 {
183 NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\([^)]+\\)|\\[[^\\]]+\\]" options:0 error:nil];
184 NSString *friendlyName = [[romFile lastPathComponent] stringByDeletingPathExtension];
185 friendlyName = [regex stringByReplacingMatchesInString:friendlyName options:0 range:NSMakeRange(0, [friendlyName length]) withTemplate:@""];
186 friendlyName = [friendlyName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
187 friendlyName = [self makeNameUnique:friendlyName];
188
189 return [self importROM:romFile withName:friendlyName keepOriginal:keep];
190 }
191
192 - (NSString *)importROM:(NSString *)romFile withName:(NSString *)friendlyName keepOriginal:(bool)keep
193 {
194 NSString *root = self.localRoot;
195 NSString *romFolder = [root stringByAppendingPathComponent:friendlyName];
196 [[NSFileManager defaultManager] createDirectoryAtPath:romFolder
197 withIntermediateDirectories:false
198 attributes:nil
199 error:nil];
200
201 NSString *newROMPath = [romFolder stringByAppendingPathComponent:romFile.lastPathComponent];
202
203 if (keep) {
204 if (copyfile(romFile.fileSystemRepresentation,
205 newROMPath.fileSystemRepresentation,
206 NULL,
207 COPYFILE_CLONE)) {
208 [[NSFileManager defaultManager] removeItemAtPath:romFolder error:nil];
209 return nil;
210 }
211 }
212 else {
213 if (![[NSFileManager defaultManager] moveItemAtPath:romFile
214 toPath:newROMPath
215 error:nil]) {
216 [[NSFileManager defaultManager] removeItemAtPath:romFolder error:nil];
217 return nil;
218 }
219 }
220
221 // Remove the Inbox directory if empty after import
222 rmdir([self.localRoot stringByAppendingPathComponent:@"Inbox"].UTF8String);
223
224 return friendlyName;
225 }
226
227 - (NSString *)renameROM:(NSString *)rom toName:(NSString *)newName
228 {
229 newName = [self makeNameUnique:newName];
230 if ([rom isEqualToString:_currentROM]) {
231 self.currentROM = newName;
232 }
233 NSString *root = self.localRoot;
234
235 [[NSFileManager defaultManager] moveItemAtPath:[root stringByAppendingPathComponent:rom]
236 toPath:[root stringByAppendingPathComponent:newName] error:nil];
237 return newName;
238 }
239
240 - (NSString *)duplicateROM:(NSString *)rom
241 {
242 NSString *newName = [self makeNameUnique:rom];
243 return [self importROM:[self romFileForROM:rom]
244 withName:newName
245 keepOriginal:true];
246 }
247
248 - (void)deleteROM:(NSString *)rom
249 {
250 NSString *root = self.localRoot;
251 NSString *romDirectory = [root stringByAppendingPathComponent:rom];
252 [[NSFileManager defaultManager] removeItemAtPath:romDirectory error:nil];
253 }
254
255
256 - (NSString *)localRoot
257 {
258 return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true).firstObject;
259 }
260 @end
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.