summaryrefslogtreecommitdiff
path: root/macosx/Source/PcsxrMemCardArray.m
diff options
context:
space:
mode:
authorSND\MaddTheSane_cp <SND\MaddTheSane_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2014-07-20 05:09:43 +0000
committerSND\MaddTheSane_cp <SND\MaddTheSane_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2014-07-20 05:09:43 +0000
commitd6942932d64a02aa92b1e04e91f6126f33fdb05e (patch)
tree7cad698308e39abc2b0e1c71674c610ec3ce74dd /macosx/Source/PcsxrMemCardArray.m
parentb8d0d24d56dbc0ee64f4ec9a72ab917604d8109d (diff)
downloadpcsxr-d6942932d64a02aa92b1e04e91f6126f33fdb05e.tar.gz
OS X: Move source files to their own folder.
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@90999 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'macosx/Source/PcsxrMemCardArray.m')
-rw-r--r--macosx/Source/PcsxrMemCardArray.m345
1 files changed, 345 insertions, 0 deletions
diff --git a/macosx/Source/PcsxrMemCardArray.m b/macosx/Source/PcsxrMemCardArray.m
new file mode 100644
index 00000000..57de81ae
--- /dev/null
+++ b/macosx/Source/PcsxrMemCardArray.m
@@ -0,0 +1,345 @@
+//
+// PcsxrMemCardArray.m
+// Pcsxr
+//
+// Created by C.W. Betts on 7/6/13.
+//
+//
+
+#import "PcsxrMemCardArray.h"
+#import "ConfigurationController.h"
+#include "sio.h"
+
+#define MAX_MEMCARD_BLOCKS 15
+
+static inline void CopyMemcardData(char *from, char *to, int srci, int dsti, char *str)
+{
+ // header
+ memmove(to + (dsti + 1) * 128, from + (srci + 1) * 128, 128);
+ SaveMcd(str, to, (dsti + 1) * 128, 128);
+
+ // data
+ memmove(to + (dsti + 1) * 1024 * 8, from + (srci+1) * 1024 * 8, 1024 * 8);
+ SaveMcd(str, to, (dsti + 1) * 1024 * 8, 1024 * 8);
+}
+
+static inline char* BlankHeader()
+{
+ struct PSXMemHeader {
+ unsigned int allocState;
+ unsigned int fileSize;
+ unsigned short nextBlock;
+ char fileName[21];
+ unsigned char garbage[96];
+ unsigned char checksum;
+ };
+
+ static struct PSXMemHeader *toReturn = NULL;
+ if (!toReturn) {
+ toReturn = calloc(sizeof(struct PSXMemHeader), 1);
+
+ //FIXME: Which value is right?
+ toReturn->allocState = 0x000000a0;
+ //toReturn->allocState = 0xa0000000;
+ toReturn->nextBlock = 0xFFFF;
+ unsigned char *bytePtr = (unsigned char*)toReturn;
+ for (int i = 0; i < sizeof(struct PSXMemHeader) - sizeof(unsigned char); i++) {
+ toReturn->checksum ^= bytePtr[i];
+ }
+ }
+
+ return (char*)toReturn;
+}
+
+static inline void ClearMemcardData(char *to, int dsti, char *str)
+{
+ // header
+ char *header = BlankHeader();
+ memcpy(to + (dsti + 1) * 128, header, 128);
+ SaveMcd(str, to, (dsti + 1) * 128, 128);
+
+ // data
+ memset(to + (dsti + 1) * 1024 * 8, 0, 1024 * 8);
+ SaveMcd(str, to, (dsti + 1) * 1024 * 8, 1024 * 8);
+}
+
+@interface PcsxrMemCardArray ()
+@property (strong) NSArray *rawArray;
+@property (readonly) char* memDataPtr;
+@property int cardNumber;
+@end
+
+@implementation PcsxrMemCardArray
+@synthesize rawArray;
+@synthesize cardNumber;
+
+- (char*)memDataPtr
+{
+ if (cardNumber == 1) {
+ return Mcd1Data;
+ } else {
+ return Mcd2Data;
+ }
+}
+
+- (const char *)memCardCPath
+{
+ if (cardNumber == 1) {
+ return Config.Mcd1;
+ } else {
+ return Config.Mcd2;
+ }
+}
+
+- (id)initWithMemoryCardNumber:(int)carNum
+{
+ NSParameterAssert(carNum == 1 || carNum == 2);
+ if (self = [super init]) {
+ NSMutableArray *tmpMemArray = [[NSMutableArray alloc] initWithCapacity:MAX_MEMCARD_BLOCKS];
+ cardNumber = carNum;
+ int i = 0, x;
+ while (i < MAX_MEMCARD_BLOCKS) {
+ x = 1;
+ McdBlock memBlock;
+ GetMcdBlockInfo(carNum, i + 1, &memBlock);
+
+ if ([PcsxrMemoryObject memFlagsFromBlockFlags:memBlock.Flags] == memFlagFree) {
+ //Free space: ignore
+ i++;
+ continue;
+ }
+ do {
+ McdBlock tmpBlock;
+ GetMcdBlockInfo(carNum, 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];
+ [tmpMemArray addObject:obj];
+ }
+ i += x;
+ }
+ self.rawArray = [[NSArray alloc] initWithArray:tmpMemArray];
+ }
+ return self;
+}
+
+- (int)indexOfFreeBlocksWithSize:(int)asize
+{
+ int foundcount = 0, i = 0;
+
+ McdBlock obj;
+ // search for empty (formatted) blocks first
+ while (i < MAX_MEMCARD_BLOCKS && foundcount < asize) {
+ GetMcdBlockInfo(cardNumber, 1 + i++, &obj);
+ //&Blocks[target_card][++i];
+ if ((obj.Flags & 0xFF) == 0xA0) { // if A0 but not A1
+ foundcount++;
+ } else if (foundcount >= 1) { // need to find n count consecutive blocks
+ foundcount = 0;
+ } else {
+ //i++;
+ }
+ //printf("formatstatus=%x\n", Info->Flags);
+ }
+
+ if (foundcount == asize)
+ return (i-foundcount);
+
+ // no free formatted slots, try to find a deleted one
+ foundcount = i = 0;
+ while (i < MAX_MEMCARD_BLOCKS && foundcount < asize) {
+ GetMcdBlockInfo(cardNumber, 1 + i++, &obj);
+ if ((obj.Flags & 0xF0) == 0xA0) { // A2 or A6 f.e.
+ foundcount++;
+ } else if (foundcount >= 1) { // need to find n count consecutive blocks
+ foundcount = 0;
+ } else {
+ //i++;
+ }
+ //printf("delstatus=%x\n", Info->Flags);
+ }
+
+ if (foundcount == asize)
+ return (i-foundcount);
+
+ return -1;
+}
+
+- (BOOL)moveBlockAtIndex:(int)idx toMemoryCard:(PcsxrMemCardArray*)otherCard
+{
+ if (idx == [rawArray count]) {
+#ifdef DEBUG
+ NSLog(@"Trying to get an object one more than the length of the raw array. Perhaps you were trying to \"move\" the free blocks. We don't want to do this.");
+#endif
+ return NO;
+ }
+ PcsxrMemoryObject *tmpObj = rawArray[idx];
+
+ int memSize = tmpObj.blockSize;
+
+ if ([otherCard availableBlocks] < memSize) {
+ NSLog(@"Failing because the other card does not have enough space!");
+ return NO;
+ }
+
+ int toCopy = [otherCard indexOfFreeBlocksWithSize:memSize];
+ if (toCopy == -1) {
+ NSLog(@"Not enough consecutive blocks. Compacting the other card.");
+ [otherCard compactMemory];
+ //Since we're accessing the mem card data directly (instead of via PcsxrMemoryObject objects) using the following calls, we don't need to reload the data.
+ toCopy = [otherCard indexOfFreeBlocksWithSize:memSize];
+ NSAssert(toCopy != -1, @"Compacting the card should have made space!");
+ }
+
+ int memIdx = tmpObj.startingIndex;
+ for (int i = 0; i < memSize; i++) {
+ CopyMemcardData([self memDataPtr], [otherCard memDataPtr], memIdx + i, toCopy + i, (char*)otherCard.memCardCPath);
+ }
+
+ return YES;
+}
+
+- (int)freeBlocks
+{
+ int memSize = MAX_MEMCARD_BLOCKS;
+ for (PcsxrMemoryObject *memObj in rawArray) {
+ memSize -= memObj.blockSize;
+ }
+ return memSize;
+}
+
+- (int)availableBlocks
+{
+ int memSize = MAX_MEMCARD_BLOCKS;
+ for (PcsxrMemoryObject *memObj in rawArray) {
+ if (memObj.flagNameIndex != memFlagDeleted) {
+ memSize -= memObj.blockSize;
+ }
+ }
+ return memSize;
+}
+
+- (NSArray*)memoryArray
+{
+ int freeSize = [self freeBlocks];
+
+ if (freeSize) {
+ McdBlock theBlock;
+ //Create a blank "block" that will be used to show the amount of free blocks
+ theBlock.Flags = 0xA0;
+ theBlock.IconCount = 0;
+ PcsxrMemoryObject *freeObj = [[PcsxrMemoryObject alloc] initWithMcdBlock:&theBlock startingIndex:MAX_MEMCARD_BLOCKS - 1 - freeSize size:freeSize];
+ return [rawArray arrayByAddingObject:freeObj];
+ } else
+ return rawArray;
+}
+
+- (NSURL*)memCardURL
+{
+ if (cardNumber == 1) {
+ return [[NSUserDefaults standardUserDefaults] URLForKey:@"Mcd1"];
+ } else {
+ return [[NSUserDefaults standardUserDefaults] URLForKey:@"Mcd2"];
+ }
+}
+
+- (int)memorySizeAtIndex:(int)idx
+{
+ if (idx == [rawArray count]) {
+#ifdef DEBUG
+ NSLog(@"Trying to get an object one more than the length of the raw array. Perhaps you were trying to \"count\" the free blocks?");
+#endif
+ return [self freeBlocks];
+ }
+
+ return [rawArray[idx] blockSize];
+}
+
+- (void)compactMemory
+{
+ int i = 0, x = 1;
+ while (i < MAX_MEMCARD_BLOCKS && x < MAX_MEMCARD_BLOCKS) {
+ x = i;
+ McdBlock baseBlock;
+ GetMcdBlockInfo(cardNumber, i+1, &baseBlock);
+ PCSXRMemFlags theFlags = [PcsxrMemoryObject memFlagsFromBlockFlags:baseBlock.Flags];
+
+ if (theFlags == memFlagDeleted || theFlags == memFlagFree) {
+ PCSXRMemFlags up1Flags = theFlags;
+ while ((up1Flags == memFlagDeleted || up1Flags == memFlagFree) && x < MAX_MEMCARD_BLOCKS) {
+ x++;
+ McdBlock up1Block;
+ GetMcdBlockInfo(cardNumber, x+1, &up1Block);
+ up1Flags = [PcsxrMemoryObject memFlagsFromBlockFlags:up1Block.Flags];
+ }
+ if (x >= MAX_MEMCARD_BLOCKS) {
+ break;
+ }
+
+ CopyMemcardData(self.memDataPtr, self.memDataPtr, x, i, (char*)[[self.memCardURL path] fileSystemRepresentation]);
+ ClearMemcardData(self.memDataPtr, x, (char*)self.memCardCPath);
+ }
+ i++;
+ }
+
+ while (i < MAX_MEMCARD_BLOCKS) {
+ ClearMemcardData(self.memDataPtr, i, (char*)self.memCardCPath);
+ i++;
+ }
+
+ LoadMcd(cardNumber, (char*)self.memCardCPath);
+}
+
+- (void)deleteMemoryBlocksAtIndex:(int)slotnum
+{
+ int xor = 0, i, j;
+ char *data, *ptr, *filename;
+ if (cardNumber == 1) {
+ filename = Config.Mcd1;
+ data = Mcd1Data;
+ } else {
+ filename = Config.Mcd2;
+ data = Mcd2Data;
+ }
+
+ if (slotnum == [rawArray count]) {
+#ifdef DEBUG
+ NSLog(@"Trying to get an object one more than the length of the raw array. Perhaps you were trying to \"delete\" the free blocks?");
+#endif
+ return;
+ }
+
+ PcsxrMemoryObject *theObj = rawArray[slotnum];
+
+ McdBlock flagBlock;
+
+ for(i = theObj.startingIndex + 1; i < (theObj.startingIndex + theObj.blockSize + 1); i++)
+ {
+ GetMcdBlockInfo(cardNumber, i, &flagBlock);
+ ptr = data + i * 128;
+
+ if ((flagBlock.Flags & 0xF0) == 0xA0) {
+ if ((flagBlock.Flags & 0xF) >= 1 &&
+ (flagBlock.Flags & 0xF) <= 3) { // deleted
+ *ptr = 0x50 | (flagBlock.Flags & 0xF);
+ } else return;
+ } else if ((flagBlock.Flags & 0xF0) == 0x50) { // used
+ *ptr = 0xA0 | (flagBlock.Flags & 0xF);
+ } else { continue; }
+
+ for (j = 0; j < 127; j++) xor ^= *ptr++;
+ *ptr = xor;
+
+ SaveMcd(filename, data, i * 128, 128);
+ }
+}
+
+@end