2013-07-08 03:10:00 +02:00
//
// PcsxrMemCardArray . m
// Pcsxr
//
// Created by C . W . Betts on 7 / 6 / 13.
//
//
# import "PcsxrMemCardArray.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 ) ;
2018-03-22 17:06:53 +01:00
SaveMcd ( str , to , ( dsti + 1 ) * 128 , 128 ) ;
2013-07-08 03:10:00 +02:00
// data
memmove ( to + ( dsti + 1 ) * 1024 * 8 , from + ( srci + 1 ) * 1024 * 8 , 1024 * 8 ) ;
2018-03-22 17:06:53 +01:00
SaveMcd ( str , to , ( dsti + 1 ) * 1024 * 8 , 1024 * 8 ) ;
2013-07-08 03:10:00 +02:00
}
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 + + ) {
2014-04-02 20:01:28 +02:00
toReturn -> checksum ^ = bytePtr [ i ] ;
2013-07-08 09:34:10 +02:00
}
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 ) ;
2018-03-22 17:06:53 +01:00
SaveMcd ( str , to , ( dsti + 1 ) * 128 , 128 ) ;
2013-07-08 05:35:06 +02:00
// data
memset ( to + ( dsti + 1 ) * 1024 * 8 , 0 , 1024 * 8 ) ;
2018-03-22 17:06:53 +01:00
SaveMcd ( str , to , ( dsti + 1 ) * 1024 * 8 , 1024 * 8 ) ;
2013-07-08 05:35:06 +02:00
}
2013-07-08 03:10:00 +02:00
@ interface PcsxrMemCardArray ( )
2013-09-10 20:18:15 +02:00
@ property ( strong ) NSArray * rawArray ;
2013-07-08 03:43:06 +02:00
@ property ( readonly ) char * memDataPtr ;
2013-09-13 23:31:56 +02:00
@ property int cardNumber ;
2013-07-08 03:10:00 +02:00
@ end
@ implementation PcsxrMemCardArray
@ synthesize rawArray ;
2013-09-13 23:31:56 +02:00
@ synthesize cardNumber ;
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 ;
}
}
2014-07-21 22:24:55 +02:00
- ( instancetype ) initWithMemoryCardNumber : ( int ) carNum
2013-07-08 03:10:00 +02:00
{
NSParameterAssert ( carNum = = 1 || carNum = = 2 ) ;
if ( self = [ super init ] ) {
NSMutableArray * tmpMemArray = [ [ NSMutableArray alloc ] initWithCapacity : MAX_MEMCARD _BLOCKS ] ;
cardNumber = carNum ;
2014-06-07 01:12:44 +02:00
int i = 0 , x ;
2013-07-08 03:10:00 +02:00
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 ) ;
2016-03-30 16:07:35 +02:00
if ( [ PcsxrMemoryObject memFlagsFromBlockFlags : memBlock . Flags ] = = PCSXRMemFlagFree ) {
2013-07-08 03:10:00 +02:00
// Free space : ignore
i + + ;
continue ;
}
2015-02-07 23:17:23 +01:00
while ( i + x < MAX_MEMCARD _BLOCKS ) {
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 ;
}
2015-02-07 23:17:23 +01:00
} ;
2013-07-10 02:04:59 +02:00
@ autoreleasepool {
PcsxrMemoryObject * obj = [ [ PcsxrMemoryObject alloc ] initWithMcdBlock : & memBlock startingIndex : i size : x ] ;
[ tmpMemArray addObject : obj ] ;
}
2013-07-08 03:10:00 +02:00
i + = x ;
}
2014-04-02 20:01:28 +02:00
self . rawArray = [ [ NSArray alloc ] initWithArray : tmpMemArray ] ;
2013-07-08 03:10:00 +02:00
}
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-11 05:24:07 +02:00
# 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
2013-07-08 03:10:00 +02:00
return NO ;
}
2013-09-10 20:43:18 +02:00
PcsxrMemoryObject * tmpObj = rawArray [ 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-11 05:24:07 +02:00
NSLog ( @ "Failing because the other card does not have enough space!" ) ;
2013-07-08 03:43:06 +02:00
return NO ;
}
int toCopy = [ otherCard indexOfFreeBlocksWithSize : memSize ] ;
if ( toCopy = = -1 ) {
2013-07-11 05:24:07 +02:00
NSLog ( @ "Not enough consecutive blocks. Compacting the other card." ) ;
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 + + ) {
2014-06-07 01:12:44 +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
{
2014-04-02 20:01:28 +02:00
int memSize = MAX_MEMCARD _BLOCKS ;
2013-07-08 03:10:00 +02:00
for ( PcsxrMemoryObject * memObj in rawArray ) {
memSize - = memObj . blockSize ;
}
return memSize ;
}
- ( int ) availableBlocks
{
int memSize = MAX_MEMCARD _BLOCKS ;
for ( PcsxrMemoryObject * memObj in rawArray ) {
2016-03-30 16:07:35 +02:00
if ( memObj . flag ! = PCSXRMemFlagDeleted ) {
2013-07-08 03:10:00 +02:00
memSize - = memObj . blockSize ;
}
}
return memSize ;
}
- ( NSArray * ) memoryArray
{
int freeSize = [ self freeBlocks ] ;
if ( freeSize ) {
McdBlock theBlock ;
2014-04-02 20:01:28 +02:00
// Create a blank "block" that will be used to show the amount of free blocks
2013-07-08 03:10:00 +02:00
theBlock . Flags = 0 xA0 ;
theBlock . IconCount = 0 ;
PcsxrMemoryObject * freeObj = [ [ PcsxrMemoryObject alloc ] initWithMcdBlock : & theBlock startingIndex : MAX_MEMCARD _BLOCKS - 1 - freeSize size : freeSize ] ;
2013-09-10 20:18:15 +02:00
return [ rawArray arrayByAddingObject : freeObj ] ;
2013-07-08 03:10:00 +02:00
} 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-11 05:26:21 +02:00
# ifdef DEBUG
2014-04-02 20:01:28 +02:00
NSLog ( @ "Trying to get an object one more than the length of the raw array. Perhaps you were trying to \" count \ " the free blocks?" ) ;
2013-07-11 05:26:21 +02:00
# endif
2013-07-08 03:10:00 +02:00
return [ self freeBlocks ] ;
}
2013-09-10 20:43:18 +02:00
return [ rawArray [ idx ] blockSize ] ;
2013-07-08 03:10:00 +02:00
}
- ( 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 ) ;
2014-11-16 22:05:39 +01:00
PCSXRMemFlag theFlags = [ PcsxrMemoryObject memFlagsFromBlockFlags : baseBlock . Flags ] ;
2013-07-08 05:35:06 +02:00
2016-03-30 16:07:35 +02:00
if ( theFlags = = PCSXRMemFlagDeleted || theFlags = = PCSXRMemFlagFree ) {
2014-11-16 22:05:39 +01:00
PCSXRMemFlag up1Flags = theFlags ;
2016-03-30 16:07:35 +02:00
while ( ( up1Flags = = PCSXRMemFlagDeleted || up1Flags = = PCSXRMemFlagFree ) && x < MAX_MEMCARD _BLOCKS ) {
2013-07-08 05:35:06 +02:00
x + + ;
McdBlock up1Block ;
GetMcdBlockInfo ( cardNumber , x + 1 , & up1Block ) ;
up1Flags = [ PcsxrMemoryObject memFlagsFromBlockFlags : up1Block . Flags ] ;
}
if ( x >= MAX_MEMCARD _BLOCKS ) {
break ;
}
2014-06-07 01:12:44 +02:00
2013-07-08 05:35:06 +02:00
CopyMemcardData ( self . memDataPtr , self . memDataPtr , x , i , ( char * ) [ [ self . memCardURL path ] fileSystemRepresentation ] ) ;
2014-06-07 01:12:44 +02:00
ClearMemcardData ( self . memDataPtr , x , ( char * ) self . memCardCPath ) ;
2013-07-08 05:35:06 +02:00
}
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
{
char * data , * ptr , * filename ;
if ( cardNumber = = 1 ) {
filename = Config . Mcd1 ;
data = Mcd1Data ;
} else {
filename = Config . Mcd2 ;
data = Mcd2Data ;
}
if ( slotnum = = [ rawArray count ] ) {
2013-07-11 05:26:21 +02:00
# ifdef DEBUG
2014-04-02 20:01:28 +02:00
NSLog ( @ "Trying to get an object one more than the length of the raw array. Perhaps you were trying to \" delete \ " the free blocks?" ) ;
2013-07-11 05:26:21 +02:00
# endif
2013-07-08 03:10:00 +02:00
return ;
}
2013-09-10 20:43:18 +02:00
PcsxrMemoryObject * theObj = rawArray [ slotnum ] ;
2013-07-08 03:10:00 +02:00
McdBlock flagBlock ;
2016-03-30 16:07:35 +02:00
for ( int i = theObj . startingIndex + 1 ; i < ( theObj . startingIndex + theObj . blockSize + 1 ) ; i + + )
2013-07-08 03:10:00 +02:00
{
2016-03-30 16:07:35 +02:00
char xor = 0 ;
2013-07-08 03:10:00 +02:00
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 ; }
2016-03-30 16:07:35 +02:00
for ( unsigned char j = 0 ; j < 127 ; j + + ) xor ^ = * ptr + + ;
2013-07-08 03:10:00 +02:00
* ptr = xor ;
2018-03-22 17:06:53 +01:00
SaveMcd ( filename , data , i * 128 , 128 ) ;
2013-07-08 03:10:00 +02:00
}
}
@ end