pcsxr/macosx/Pcsxr-QL/PSXMemEnumerator.m

181 lines
3.9 KiB
Objective-C

//
// PSXMemEnumerator.c
// Pcsxr
//
// Created by C.W. Betts on 7/20/14.
//
//
#include <stdio.h>
#import "PSXMemEnumerator.h"
#define MAX_MEMCARD_BLOCKS 15
static void GetSoloBlockInfo(unsigned char *data, int block, McdBlock *Info)
{
unsigned char *ptr = data + block * 8192 + 2;
unsigned char *str = Info->Title;
unsigned short clut[16];
unsigned char * sstr = Info->sTitle;
unsigned short c;
int i, x = 0;
memset(Info, 0, sizeof(McdBlock));
Info->IconCount = *ptr & 0x3;
ptr += 2;
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;
}
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, 13);
ptr += 12;
strlcpy(Info->Name, ptr, 17);
}
static inline PCSXRMemFlag MemBlockFlag(unsigned char blockFlags)
{
if ((blockFlags & 0xF0) == 0xA0) {
if ((blockFlags & 0xF) >= 1 && (blockFlags & 0xF) <= 3)
return PCSXRMemFlagDeleted;
else
return PCSXRMemFlagFree;
} else if ((blockFlags & 0xF0) == 0x50) {
if ((blockFlags & 0xF) == 0x1)
return PCSXRMemFlagUsed;
else if ((blockFlags & 0xF) == 0x2)
return PCSXRMemFlagLink;
else if ((blockFlags & 0xF) == 0x3)
return PCSXRMemFlagEndLink;
} else
return PCSXRMemFlagFree;
//Xcode complains unless we do this...
//NSLog(@"Unknown flag %x", blockFlags);
return PCSXRMemFlagFree;
}
NSArray *CreateArrayByEnumeratingMemoryCardAtURL(NSURL *location)
{
NSMutableArray *memArray = [[NSMutableArray alloc] initWithCapacity:MAX_MEMCARD_BLOCKS];
if (!location) {
return nil;
}
NSData *fileData = [[NSData alloc] initWithContentsOfURL:location options:NSDataReadingMappedIfSafe error:NULL];
if (!fileData) {
return nil;
}
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 nil;
int i = 0, x;
while (i < MAX_MEMCARD_BLOCKS) {
x = 1;
McdBlock memBlock;
GetSoloBlockInfo((unsigned char *)memPtr, i + 1, &memBlock);
if (MemBlockFlag(memBlock.Flags) == PCSXRMemFlagFree) {
//Free space: ignore
i++;
continue;
}
while (i + x < MAX_MEMCARD_BLOCKS) {
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;
}
};
PcsxrMemoryObject *obj = [[PcsxrMemoryObject alloc] initWithMcdBlock:&memBlock startingIndex:i size:x];
i += x;
if (MemBlockFlag(memBlock.Flags) == PCSXRMemFlagDeleted) {
continue;
}
[memArray addObject:obj];
}
return [[NSArray alloc] initWithArray:memArray];
}