From d6942932d64a02aa92b1e04e91f6126f33fdb05e Mon Sep 17 00:00:00 2001 From: "SND\\MaddTheSane_cp" Date: Sun, 20 Jul 2014 05:09:43 +0000 Subject: 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 --- macosx/Source/PcsxrMemCardArray.m | 345 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 macosx/Source/PcsxrMemCardArray.m (limited to 'macosx/Source/PcsxrMemCardArray.m') 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 -- cgit v1.2.3