summaryrefslogtreecommitdiff
path: root/macosx/Psx-Memcard/GetMetadataForFile.m
diff options
context:
space:
mode:
authorSND\MaddTheSane_cp <SND\MaddTheSane_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2014-06-06 18:42:33 +0000
committerSND\MaddTheSane_cp <SND\MaddTheSane_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2014-06-06 18:42:33 +0000
commit3bd0bcc5dfe1777a2446a897f170f4c5971baa83 (patch)
tree6266ecfb0194121a99aaeed016b9d15c28cf0078 /macosx/Psx-Memcard/GetMetadataForFile.m
parent99d48611d9604491cc2e95380a2b13e00db4d4b5 (diff)
downloadpcsxr-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/Psx-Memcard/GetMetadataForFile.m')
-rw-r--r--macosx/Psx-Memcard/GetMetadataForFile.m197
1 files changed, 197 insertions, 0 deletions
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