2013-07-08 03:10:00 +02:00
//
// PcsxrMemCardArray . m
// Pcsxr
//
// Created by C . W . Betts on 7 / 6 / 13.
//
//
# import "PcsxrMemCardArray.h"
# import "ARCBridge.h"
# import "ConfigurationController.h"
2013-07-08 05:35:06 +02:00
# include "sio.h"
2013-07-08 03:10:00 +02:00
# 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 ) ;
}
2013-07-08 09:34:10 +02:00
static inline char * BlankHeader ( )
2013-07-08 05:35:06 +02:00
{
struct PSXMemHeader {
unsigned int allocState ;
unsigned int fileSize ;
unsigned short nextBlock ;
char fileName [ 21 ] ;
unsigned char garbage [ 96 ] ;
unsigned char checksum ;
} ;
2013-07-08 09:26:30 +02:00
2013-07-08 09:34:10 +02:00
static struct PSXMemHeader * toReturn = NULL ;
if ( ! toReturn ) {
toReturn = calloc ( sizeof ( struct PSXMemHeader ) , 1 ) ;
// FIXME : Which value is right ?
toReturn -> allocState = 0 x000000a0 ;
// toReturn -> allocState = 0 xa0000000 ;
toReturn -> nextBlock = 0 xFFFF ;
unsigned char * bytePtr = ( unsigned char * ) toReturn ;
for ( int i = 0 ; i < sizeof ( struct PSXMemHeader ) - sizeof ( unsigned char ) ; i + + ) {
toReturn -> checksum = toReturn -> checksum ^ bytePtr [ i ] ;
}
2013-07-08 05:35:06 +02:00
}
return ( char * ) toReturn ;
}
static inline void ClearMemcardData ( char * to , int dsti , char * str )
{
// header
2013-07-08 09:34:10 +02:00
char * header = BlankHeader ( ) ;
2013-07-08 05:35:06 +02:00
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 ) ;
}
2013-07-08 03:10:00 +02:00
@ interface PcsxrMemCardArray ( )
@ property ( arcretain ) NSArray * rawArray ;
2013-07-08 03:43:06 +02:00
@ property ( readonly ) char * memDataPtr ;
2013-07-08 03:10:00 +02:00
@ end
@ implementation PcsxrMemCardArray
@ synthesize rawArray ;
2013-07-08 03:43:06 +02:00
- ( char * ) memDataPtr
{
if ( cardNumber = = 1 ) {
return Mcd1Data ;
} else {
return Mcd2Data ;
}
}
2013-07-08 03:10:00 +02:00
2013-07-08 05:35:06 +02:00
- ( const char * ) memCardCPath
{
if ( cardNumber = = 1 ) {
return Config . Mcd1 ;
} else {
return Config . Mcd2 ;
}
}
2013-07-08 03:10:00 +02:00
- ( 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 , x ;
i = 0 ;
while ( i < MAX_MEMCARD _BLOCKS ) {
x = 1 ;
2013-07-10 02:04:59 +02:00
McdBlock memBlock ;
2013-07-08 03:10:00 +02:00
GetMcdBlockInfo ( carNum , i + 1 , & memBlock ) ;
if ( [ PcsxrMemoryObject memFlagsFromBlockFlags : memBlock . Flags ] = = memFlagFree ) {
// Free space : ignore
i + + ;
continue ;
}
do {
2013-07-10 02:04:59 +02:00
McdBlock tmpBlock ;
2013-07-08 03:10:00 +02:00
GetMcdBlockInfo ( carNum , i + x + 1 , & tmpBlock ) ;
if ( ( tmpBlock . Flags & 0 x3 ) = = 0 x3 ) {
x + + ;
break ;
} else if ( ( tmpBlock . Flags & 0 x2 ) = = 0 x2 ) {
x + + ;
} else {
break ;
}
} while ( i + x - 1 < MAX_MEMCARD _BLOCKS ) ;
2013-07-10 02:04:59 +02:00
@ autoreleasepool {
PcsxrMemoryObject * obj = [ [ PcsxrMemoryObject alloc ] initWithMcdBlock : & memBlock startingIndex : i size : x ] ;
[ tmpMemArray addObject : obj ] ;
RELEASEOBJ ( obj ) ;
}
2013-07-08 03:10:00 +02:00
i + = x ;
}
self . rawArray = [ NSArray arrayWithArray : tmpMemArray ] ;
RELEASEOBJ ( 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 & 0 xFF ) = = 0 xA0 ) { // 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 & 0 xF0 ) = = 0 xA0 ) { // 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 ] ) {
2013-07-09 09:07:15 +02:00
SysPrintf ( "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.\n" ) ;
2013-07-08 03:10:00 +02:00
return NO ;
}
2013-07-08 03:43:06 +02:00
PcsxrMemoryObject * tmpObj = [ rawArray objectAtIndex : idx ] ;
2013-07-08 03:10:00 +02:00
2013-07-08 03:43:06 +02:00
int memSize = tmpObj . blockSize ;
if ( [ otherCard availableBlocks ] < memSize ) {
2013-07-09 09:07:15 +02:00
SysPrintf ( "Failing because the other card does not have enough space!\n" ) ;
2013-07-08 03:43:06 +02:00
return NO ;
}
int toCopy = [ otherCard indexOfFreeBlocksWithSize : memSize ] ;
if ( toCopy = = -1 ) {
2013-07-09 09:07:15 +02:00
SysPrintf ( "Not enough consecutive blocks. Compacting the other card.\n" ) ;
2013-07-08 03:43:06 +02:00
[ otherCard compactMemory ] ;
2013-07-08 09:26:30 +02:00
// 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 .
2013-07-08 03:43:06 +02:00
toCopy = [ otherCard indexOfFreeBlocksWithSize : memSize ] ;
NSAssert ( toCopy ! = -1 , @ "Compacting the card should have made space!" ) ;
}
int memIdx = tmpObj . startingIndex ;
2013-07-09 09:07:15 +02:00
for ( int i = 0 ; i < memSize ; i + + ) {
2013-07-08 05:35:06 +02:00
CopyMemcardData ( [ self memDataPtr ] , [ otherCard memDataPtr ] , ( memIdx + i ) , ( toCopy + i ) , ( char * ) otherCard . memCardCPath ) ;
2013-07-08 03:43:06 +02:00
}
2013-07-08 03:10:00 +02:00
2013-07-08 03:43:06 +02:00
return YES ;
2013-07-08 03:10:00 +02:00
}
- ( int ) freeBlocks
{
int memSize = 15 ;
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 for
theBlock . Flags = 0 xA0 ;
theBlock . IconCount = 0 ;
PcsxrMemoryObject * freeObj = [ [ PcsxrMemoryObject alloc ] initWithMcdBlock : & theBlock startingIndex : MAX_MEMCARD _BLOCKS - 1 - freeSize size : freeSize ] ;
return [ rawArray arrayByAddingObject : AUTORELEASEOBJ ( freeObj ) ] ;
} else
return rawArray ;
}
2013-07-08 03:43:06 +02:00
- ( NSURL * ) memCardURL
2013-07-08 03:10:00 +02:00
{
if ( cardNumber = = 1 ) {
return [ [ NSUserDefaults standardUserDefaults ] URLForKey : @ "Mcd1" ] ;
} else {
return [ [ NSUserDefaults standardUserDefaults ] URLForKey : @ "Mcd2" ] ;
}
}
- ( int ) memorySizeAtIndex : ( int ) idx
{
if ( idx = = [ rawArray count ] ) {
2013-07-09 09:07:15 +02:00
SysPrintf ( "Trying to get an object one more than the length of the raw array. Perhaps you were trying to \" count \ " the free blocks.\n" ) ;
2013-07-08 03:10:00 +02:00
return [ self freeBlocks ] ;
}
return [ [ rawArray objectAtIndex : idx ] blockSize ] ;
}
- ( void ) compactMemory
{
2013-07-08 05:35:06 +02:00
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 + + ;
}
2013-07-08 03:10:00 +02:00
2013-07-08 05:35:06 +02:00
LoadMcd ( cardNumber , ( char * ) self . memCardCPath ) ;
2013-07-08 03:10:00 +02:00
}
- ( 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 ] ) {
2013-07-09 09:07:15 +02:00
SysPrintf ( "Trying to get an object one more than the length of the raw array. Perhaps you were trying to \" delete \ " the free blocks.\n" ) ;
2013-07-08 03:10:00 +02:00
return ;
}
PcsxrMemoryObject * theObj = [ rawArray objectAtIndex : 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 & 0 xF0 ) = = 0 xA0 ) {
if ( ( flagBlock . Flags & 0 xF ) >= 1 &&
( flagBlock . Flags & 0 xF ) <= 3 ) { // deleted
* ptr = 0 x50 | ( flagBlock . Flags & 0 xF ) ;
} else return ;
} else if ( ( flagBlock . Flags & 0 xF0 ) = = 0 x50 ) { // used
* ptr = 0 xA0 | ( flagBlock . Flags & 0 xF ) ;
} else { continue ; }
for ( j = 0 ; j < 127 ; j + + ) xor ^ = * ptr + + ;
* ptr = xor ;
SaveMcd ( filename , data , i * 128 , 128 ) ;
}
}
2013-07-08 03:43:06 +02:00
# if ! __has _feature ( objc_arc )
- ( void ) dealloc
{
self . rawArray = nil ;
[ super dealloc ] ;
}
# endif
2013-07-08 03:10:00 +02:00
@ end