diff options
| author | SND\MaddTheSane_cp <SND\MaddTheSane_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2014-06-06 18:42:33 +0000 |
|---|---|---|
| committer | SND\MaddTheSane_cp <SND\MaddTheSane_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2014-06-06 18:42:33 +0000 |
| commit | 3bd0bcc5dfe1777a2446a897f170f4c5971baa83 (patch) | |
| tree | 6266ecfb0194121a99aaeed016b9d15c28cf0078 /macosx | |
| parent | 99d48611d9604491cc2e95380a2b13e00db4d4b5 (diff) | |
| download | pcsxr-3bd0bcc5dfe1777a2446a897f170f4c5971baa83.tar.gz | |
OS X: implement the metadata (Spotlight) importer for the memory cards.
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@90603 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'macosx')
| -rw-r--r-- | macosx/Pcsxr.xcodeproj/project.pbxproj | 9 | ||||
| -rwxr-xr-x | macosx/PcsxrMemoryObject.m | 2 | ||||
| -rw-r--r-- | macosx/Psx-Memcard/GetMetadataForFile.m | 197 | ||||
| -rw-r--r-- | macosx/Psx-Memcard/en.lproj/schema.strings | 10 | ||||
| -rw-r--r-- | macosx/Psx-Memcard/schema.xml | 29 |
5 files changed, 228 insertions, 19 deletions
diff --git a/macosx/Pcsxr.xcodeproj/project.pbxproj b/macosx/Pcsxr.xcodeproj/project.pbxproj index 2f7413f4..bfb98828 100644 --- a/macosx/Pcsxr.xcodeproj/project.pbxproj +++ b/macosx/Pcsxr.xcodeproj/project.pbxproj @@ -179,6 +179,8 @@ 5525BC6B19421A760018AF2F /* GetMetadataForFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 5525BC6A19421A760018AF2F /* GetMetadataForFile.m */; }; 5525BC7819421D4F0018AF2F /* schema.xml in Resources */ = {isa = PBXBuildFile; fileRef = 5525BC7719421D4F0018AF2F /* schema.xml */; }; 5525BC7C194221EC0018AF2F /* schema.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5525BC7E194221EC0018AF2F /* schema.strings */; }; + 5525BC80194228460018AF2F /* PcsxrMemoryObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 55A90228147D89380037E18F /* PcsxrMemoryObject.m */; }; + 5525BC8119423FA90018AF2F /* Psx-Memcard.mdimporter in Copy Spotlight Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5525BC5D19421A750018AF2F /* Psx-Memcard.mdimporter */; }; 55268A5A1876244E00A82269 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 551A74A317868B110052D185 /* Foundation.framework */; }; 5529EA11169CBE3400BAA2A5 /* RecentItemsMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 5550D2721683C923006C56B5 /* RecentItemsMenu.m */; }; 553FECEE18DF5A8300C7B007 /* AddPluginSheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 553FECB818DF5A8300C7B007 /* AddPluginSheet.xib */; }; @@ -407,13 +409,15 @@ name = "Copy QuickLook Plug-In"; runOnlyForDeploymentPostprocessing = 0; }; - 5525BC58194219B80018AF2F /* CopyFiles */ = { + 5525BC58194219B80018AF2F /* Copy Spotlight Plug-Ins */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = Contents/Library/Spotlight; dstSubfolderSpec = 1; files = ( + 5525BC8119423FA90018AF2F /* Psx-Memcard.mdimporter in Copy Spotlight Plug-Ins */, ); + name = "Copy Spotlight Plug-Ins"; runOnlyForDeploymentPostprocessing = 0; }; 71AD2DF010C3573400365243 /* Copy Plug-Ins */ = { @@ -1829,7 +1833,7 @@ 2BB3D6C505427FE200831ACB /* Frameworks */, 71AD2DF010C3573400365243 /* Copy Plug-Ins */, 55202EBA18E73E3E00C631AA /* Copy QuickLook Plug-In */, - 5525BC58194219B80018AF2F /* CopyFiles */, + 5525BC58194219B80018AF2F /* Copy Spotlight Plug-Ins */, 55F41A3317EF8CFF00605DF8 /* Strip Headers */, ); buildRules = ( @@ -2503,6 +2507,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5525BC80194228460018AF2F /* PcsxrMemoryObject.m in Sources */, 5525BC6919421A760018AF2F /* main.c in Sources */, 5525BC6B19421A760018AF2F /* GetMetadataForFile.m in Sources */, ); diff --git a/macosx/PcsxrMemoryObject.m b/macosx/PcsxrMemoryObject.m index a26f1829..7d11b6f8 100755 --- a/macosx/PcsxrMemoryObject.m +++ b/macosx/PcsxrMemoryObject.m @@ -19,7 +19,7 @@ NSString *const memoryAnimateTimerKey = @"PCSXR Memory Card Image Animate"; @property (readwrite) uint8_t startingIndex; @property (readwrite) uint8_t blockSize; -@property (readwrite, nonatomic) NSInteger memImageIndex; +@property (nonatomic) NSInteger memImageIndex; @property (strong) NSArray *memImages; @property (readwrite) PCSXRMemFlags flagNameIndex; @end diff --git a/macosx/Psx-Memcard/GetMetadataForFile.m b/macosx/Psx-Memcard/GetMetadataForFile.m index 731cd928..ed0e8dd3 100644 --- a/macosx/Psx-Memcard/GetMetadataForFile.m +++ b/macosx/Psx-Memcard/GetMetadataForFile.m @@ -9,6 +9,14 @@ #include <CoreFoundation/CoreFoundation.h> #import <Foundation/Foundation.h> #include "GetMetadataForFile.h" +#include "PcsxrMemoryObject.h" + +#define MAX_MEMCARD_BLOCKS 15 +#define kPCSXRSaveNames @"com_codeplex_pcsxr_memcard_savenames" +#define kPCSXRMemCount @"com_codeplex_pcsxr_memcard_memcount" +#define kPCSXRFreeBlocks @"com_codeplex_pcsxr_memcard_freeblocks" +#define kPCSXRMemNames @"com_codeplex_pcsxr_memcard_memnames" +#define kPCSXRMemIDs @"com_codeplex_pcsxr_memcard_memids" //============================================================================== // @@ -20,13 +28,202 @@ // //============================================================================== +static void trimPriv(char *str) { + int pos = 0; + char *dest = str; + + // skip leading blanks + while (str[pos] <= ' ' && str[pos] > 0) + pos++; + + while (str[pos]) { + *(dest++) = str[pos]; + pos++; + } + + *(dest--) = '\0'; // store the null + + // remove trailing blanks + while (dest >= str && *dest <= ' ' && *dest > 0) + *(dest--) = '\0'; +} + +static void GetSoloBlockInfo(unsigned char *data, int block, McdBlock *Info) +{ + unsigned char *ptr, *str, *sstr; + unsigned short clut[16]; + unsigned short c; + int i, x; + + memset(Info, 0, sizeof(McdBlock)); + + ptr = data + block * 8192 + 2; + + Info->IconCount = *ptr & 0x3; + + ptr += 2; + + x = 0; + + str = Info->Title; + sstr = Info->sTitle; + + for (i = 0; i < 48; i++) { + c = *(ptr) << 8; + c |= *(ptr + 1); + if (!c) break; + + // Convert ASCII characters to half-width + if (c >= 0x8281 && c <= 0x829A) + c = (c - 0x8281) + 'a'; + else if (c >= 0x824F && c <= 0x827A) + c = (c - 0x824F) + '0'; + else if (c == 0x8140) c = ' '; + else if (c == 0x8143) c = ','; + else if (c == 0x8144) c = '.'; + else if (c == 0x8146) c = ':'; + else if (c == 0x8147) c = ';'; + else if (c == 0x8148) c = '?'; + else if (c == 0x8149) c = '!'; + else if (c == 0x815E) c = '/'; + else if (c == 0x8168) c = '"'; + else if (c == 0x8169) c = '('; + else if (c == 0x816A) c = ')'; + else if (c == 0x816D) c = '['; + else if (c == 0x816E) c = ']'; + else if (c == 0x817C) c = '-'; + else { + str[i] = ' '; + sstr[x++] = *ptr++; sstr[x++] = *ptr++; + continue; + } + + str[i] = sstr[x++] = c; + ptr += 2; + } + + trimPriv(str); + trimPriv(sstr); + + ptr = data + block * 8192 + 0x60; // icon palette data + + for (i = 0; i < 16; i++) { + clut[i] = *((unsigned short *)ptr); + ptr += 2; + } + + for (i = 0; i < Info->IconCount; i++) { + short *icon = &Info->Icon[i * 16 * 16]; + + ptr = data + block * 8192 + 128 + 128 * i; // icon data + + for (x = 0; x < 16 * 16; x++) { + icon[x++] = clut[*ptr & 0xf]; + icon[x] = clut[*ptr >> 4]; + ptr++; + } + } + + ptr = data + block * 128; + + Info->Flags = *ptr; + + ptr += 0xa; + strlcpy(Info->ID, ptr, 12); + ptr += 12; + strlcpy(Info->Name, ptr, 16); +} + +static Boolean PopulateMemCards(NSData *fileData, NSArray **outArray) +{ + NSMutableArray *memArray = [[NSMutableArray alloc] initWithCapacity:MAX_MEMCARD_BLOCKS]; + if (!fileData) { + *outArray = @[]; + return FALSE; + } + const unsigned char *memPtr = [fileData bytes]; + if ([fileData length] == MCD_SIZE + 64) + memPtr += 64; + else if([fileData length] == MCD_SIZE + 3904) + memPtr += 3904; + else if ([fileData length] != MCD_SIZE) + return FALSE; + + int i = 0, x; + while (i < MAX_MEMCARD_BLOCKS) { + x = 1; + McdBlock memBlock; + GetSoloBlockInfo((unsigned char *)memPtr, i + 1, &memBlock); + + if ([PcsxrMemoryObject memFlagsFromBlockFlags:memBlock.Flags] == memFlagFree) { + //Free space: ignore + i++; + continue; + } + do { + McdBlock tmpBlock; + GetSoloBlockInfo((unsigned char *)memPtr, i + x + 1, &tmpBlock); + if ((tmpBlock.Flags & 0x3) == 0x3) { + x++; + break; + } else if ((tmpBlock.Flags & 0x2) == 0x2) { + x++; + } else { + break; + } + } while (i + x - 1 < MAX_MEMCARD_BLOCKS); + @autoreleasepool { + PcsxrMemoryObject *obj = [[PcsxrMemoryObject alloc] initWithMcdBlock:&memBlock startingIndex:i size:x]; + [memArray addObject:obj]; + } + i += x; + } + + *outArray = [[NSArray alloc] initWithArray:memArray]; + return true; +} + Boolean GetMetadataForFile(void *thisInterface, CFMutableDictionaryRef attributes, CFStringRef contentTypeUTI, CFStringRef pathToFile) { Boolean ok = FALSE; @autoreleasepool { + short freeBlocks = MAX_MEMCARD_BLOCKS; + short memCount = 0; + NSMutableArray *enNames = [[NSMutableArray alloc] initWithCapacity:MAX_MEMCARD_BLOCKS]; + NSMutableArray *jpNames = [[NSMutableArray alloc] initWithCapacity:MAX_MEMCARD_BLOCKS]; + NSMutableArray *memNames = [[NSMutableArray alloc] initWithCapacity:MAX_MEMCARD_BLOCKS]; + NSMutableArray *memIDs = [[NSMutableArray alloc] initWithCapacity:MAX_MEMCARD_BLOCKS]; NSMutableDictionary *attr = (__bridge NSMutableDictionary*)attributes; NSString *path = (__bridge NSString*)pathToFile; + NSArray *cardArrays; + NSData *fileData = [[NSData alloc] initWithContentsOfFile:path options:NSDataReadingMappedIfSafe error:NULL]; + if (!fileData) { + return FALSE; + } + ok = PopulateMemCards(fileData, &cardArrays); + if (!ok) { + return FALSE; + } + for (PcsxrMemoryObject *obj in cardArrays) { + // Ignore deleted blocks + if (obj.flagNameIndex == memFlagDeleted) { + continue; + } + freeBlocks -= obj.blockSize; + memCount++; + [enNames addObject:obj.englishName]; + [jpNames addObject:obj.sjisName]; + [memNames addObject:obj.memName]; + [memIDs addObject:obj.memID]; + } + + attr[kPCSXRSaveNames] = @{@"en": [enNames copy], + @"jp": [jpNames copy]}; + attr[kPCSXRMemCount] = @(memCount); + attr[kPCSXRFreeBlocks] = @(freeBlocks); + attr[kPCSXRMemNames] = [memNames copy]; + attr[kPCSXRMemIDs] = [memIDs copy]; } // Return the status diff --git a/macosx/Psx-Memcard/en.lproj/schema.strings b/macosx/Psx-Memcard/en.lproj/schema.strings index b0dfaeab..2b660a4e 100644 --- a/macosx/Psx-Memcard/en.lproj/schema.strings +++ b/macosx/Psx-Memcard/en.lproj/schema.strings @@ -13,8 +13,18 @@ /* The form is: "myMetadataKey" = "My Metadata Key"; */ /* The name on the left is the name defined in schema.xml */ /* The name on the right is what the user will see */ +"com_codeplex_pcsxr_memcard_memcount" = "Saves"; +"com_codeplex_pcsxr_memcard_freeblocks" = "Free Blocks"; +"com_codeplex_pcsxr_memcard_savenames" = "Saved Games"; +"com_codeplex_pcsxr_memcard_memnames" = "Memory Block Names"; +"com_codeplex_pcsxr_memcard_memids" = "Memory Block IDs"; /* Localized Description of you custom metadata attributes */ /* The form is: "myMetadataKey.Description" = "stuff"; /* com_Foo_YourAttrName should be definded in the schema.xml file */ /* The value on the right will be displayed by the Finder etc.. */ +"com_codeplex_pcsxr_memcard_memcount.Description" = "Number of individual save games"; +"com_codeplex_pcsxr_memcard_freeblocks.Description" = "Number of blocks that are free"; +"com_codeplex_pcsxr_memcard_savenames.Description" = "The names of the games saved on the memory card"; +"com_codeplex_pcsxr_memcard_memnames.Description" = "The names of the memory blocks"; +"com_codeplex_pcsxr_memcard_memids.Descriptions" = "IDs of memory cards"; diff --git a/macosx/Psx-Memcard/schema.xml b/macosx/Psx-Memcard/schema.xml index 4e072263..a4577fed 100644 --- a/macosx/Psx-Memcard/schema.xml +++ b/macosx/Psx-Memcard/schema.xml @@ -25,16 +25,11 @@ --> <attributes> - <!-- - <attribute name="net_sourceforge_playerpro_tracker_instumentlist" multivalued="true" type="CFString"/> - <attribute name="net_sourceforge_playerpro_tracker_patternlist" multivalued="true" type="CFString"/> - <attribute name="net_sourceforge_playerpro_tracker_totalpatterns" multivalued="false" nosearch="true" type="CFNumber"/> - <attribute name="net_sourceforge_playerpro_tracker_partitionlength" multivalued="false" nosearch="true" type="CFNumber"/> - <attribute name="net_sourceforge_playerpro_tracker_totalinstruments" multivalued="false" nosearch="true" type="CFNumber"/> - <attribute name="net_sourceforge_playerpro_tracker_totaltracks" multivalued="false" nosearch="true" type="CFNumber"/> - <attribute name="net_sourceforge_playerpro_tracker_formatdescription" multivalued="false" nosearch="true" type="CFString"/> - <attribute name="net_sourceforge_playerpro_tracker_madkinfo" multivalued="false" type="CFString" /> - --> + <attribute name="com_codeplex_pcsxr_memcard_memcount" multivalued="false" nosearch="true" type="CFNumber"/> + <attribute name="com_codeplex_pcsxr_memcard_freeblocks" multivalued="false" nosearch="true" type="CFNumber"/> + <attribute name="com_codeplex_pcsxr_memcard_savenames" multivalued="true" type="CFString"/> + <attribute name="com_codeplex_pcsxr_memcard_memnames" multivalued="true" type="CFString"/> + <attribute name="com_codeplex_pcsxr_memcard_memids" multivalued="true" type="CFString"/> </attributes> <types> @@ -43,15 +38,17 @@ <!-- 'allattrs' is a whitespace separated list of all of the attributes that this UTI type normally has. It does not have to be exhaustive. --> <allattrs> - kMDItemTitle - kMDItemDurationSeconds - kMDItemCodecs + com_codeplex_pcsxr_memcard_memcount + com_codeplex_pcsxr_memcard_freeblocks + com_codeplex_pcsxr_memcard_savenames + com_codeplex_pcsxr_memcard_memnames + com_codeplex_pcsxr_memcard_memids </allattrs> <!-- 'displayattrs' is a whitespace separated list of the attributes that should normally be displayed when previewing files of this UTI type. --> <displayattrs> - kMDItemTitle - kMDItemDurationSeconds - kMDItemCodecs + com_codeplex_pcsxr_memcard_memcount + com_codeplex_pcsxr_memcard_freeblocks + com_codeplex_pcsxr_memcard_savenames </displayattrs> </type> |
