git.y1.nz

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.