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
This commit is contained in:
SND\MaddTheSane_cp 2014-06-06 18:42:33 +00:00
parent 99d48611d9
commit 3bd0bcc5df
5 changed files with 228 additions and 19 deletions

View File

@ -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 */,
);

View File

@ -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

View File

@ -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

View File

@ -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";

View File

@ -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>