Merge pull request #41 from DacoTaco/CardFixes

fix memory card raw access to use the (new) exposed libogc functions
This commit is contained in:
suloku 2021-10-07 12:19:44 +02:00 committed by GitHub
commit 756289094a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 135 additions and 78 deletions

View File

@ -20,7 +20,7 @@
#include "background_bmp.h"
extern GCI gci;
extern card_direntry gci;
//*extern GXRModeObj *vmode; /*** Graphics Mode Object ***/
//extern u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/
//extern int whichfb = 0; /*** Frame buffer toggle ***/

View File

@ -27,6 +27,8 @@ distribution.
-------------------------------------------------------------*/
#include <ogc/libversion.h>
#if (_V_MAJOR_ <= 2) && (_V_MINOR_ <= 2)
#include <stdlib.h>
#include <stdio.h>
@ -247,6 +249,11 @@ s32 __card_sectorerase(s32 chn,u32 sector,cardcallback callback);
static s32 __card_onreset(s32 final);
s32 CARD_GetSerialNo(s32 chn,u32 *serial1,u32 *serial2);
#define ogc_card_sync __card_sync
#define ogc_card_read __card_read
#define ogc_card_sectorerase __card_sectorerase
#define ogc_card_write __card_write
static sys_resetinfo card_resetinfo = {
{},
__card_onreset,
@ -3311,3 +3318,5 @@ s32 CARD_GetFreeBlocks(s32 chn, u16* freeblocks)
return ret;
}
#endif

View File

@ -27,10 +27,12 @@ distribution.
-------------------------------------------------------------*/
#ifndef __CARD_H__
#define __CARD_H__
#include <ogc/libversion.h>
#if (_V_MAJOR_ <= 2) && (_V_MINOR_ <= 2)
/*!
\file card.h
\brief Memory card subsystem
@ -646,3 +648,5 @@ s32 __card_sectorerase(s32 chn,u32 sector,cardcallback callback);
#endif /* __cplusplus */
#endif
#endif

View File

@ -75,7 +75,7 @@ extern u32 retraceCount;
extern card_dir CardList[];
extern u8 filelist[1024][1024];
extern u32 maxfile;
extern GCI gci;
extern card_direntry gci;
#define MAXFILEBUFFER (1024 * 2048)
extern u8 FileBuffer[MAXFILEBUFFER] ATTRIBUTE_ALIGN (32);
extern u8 CommentBuffer[64] ATTRIBUTE_ALIGN (32);
@ -969,7 +969,7 @@ void showSaveInfo(int sel)
y += 10;
// Compute date/time
u32 t = gci.time; // seconds since jan 1, 2000
u32 t = gci.last_modified; // seconds since jan 1, 2000
/*
//Raw time display
sprintf(txt, "D: %08X", t);
@ -1025,22 +1025,22 @@ void showSaveInfo(int sel)
sprintf(txt, "Time: %02d:%02d:%02d", hour, min, sec);
DrawText(x, y, txt);
y += 20;
sprintf(txt, "Blocks: %02d (%d free)", gci.filesize8, FreeBlocks(MEM_CARD));
sprintf(txt, "Blocks: %02d (%d free)", gci.length, FreeBlocks(MEM_CARD));
DrawText(x, y, txt);
y += 20;
//M-> Cant' move the file //C->can't copy the file //P->public file //Most frecuent: xxP
/* sprintf(txt, "Perm: %s%s%s",
(gci.unknown1 & 16) ? "M " : "x ",
(gci.unknown1 & 8) ? "C " : "x ",
(gci.unknown1 & 4) ? "P" : "x");
(gci.permission & 16) ? "M " : "x ",
(gci.permission & 8) ? "C " : "x ",
(gci.permission & 4) ? "P" : "x");
*/
sprintf(txt, "Perm: %s%s%s",
(gci.unknown1 & 16) ? "" : "Move | ",
(gci.unknown1 & 8) ? "" : "Copy | ",
(gci.unknown1 & 4) ? "Public" : "Private");
(gci.permission & 16) ? "" : "Move | ",
(gci.permission & 8) ? "" : "Copy | ",
(gci.permission & 4) ? "Public" : "Private");
DrawText(x, y, txt);
y += 20;
sprintf(txt, "Copy Count: %02d", gci.unknown2);
sprintf(txt, "Copy Count: %02d", gci.copy_times);
DrawText(x, y, txt);
#ifdef DEBUG_VALUES

View File

@ -7,7 +7,28 @@
#define __GCIHDR_
#include <gccore.h>
#include <ogc/libversion.h>
#if (_V_MAJOR_ <= 2) && (_V_MINOR_ <= 2)
typedef struct _card_direntry {
u8 gamecode[4];
u8 company[2];
u8 pad_00;
u8 banner_fmt;
u8 filename[CARD_FILENAMELEN];
u32 last_modified;
u32 icon_addr;
u16 icon_fmt;
u16 icon_speed;
u8 permission;
u8 copy_times;
u16 block;
u16 length;
u16 pad_01;
u32 comment_addr;
} card_direntry;
#else
#include <ogc/card.h>
#endif
// If STATUSOGC defined uses CARD_GetStatus and CARD_SetStatus
// Default (undefined) uses __card_getstatusex and __card_setstatusex
// Diference: when restoring a savegame with the ex functions original time, copy counter, etc are preserved
@ -21,24 +42,6 @@
#define SDCARD_GetIconSpeedBounce(icon_speed,n,i) ((n) < (i) ? (((icon_speed)>>(2*(n))) & 0x03) : (((icon_speed)>>(2*((i*2)-2-n)) & 0x03)) )
#define SDCARD_GetIconAnim(banner_fmt) ((banner_fmt) & 0x04)
typedef struct {
u8 gamecode[4];
u8 company[2];
u8 reserved01; /*** Always 0xff ***/
u8 banner_fmt;
u8 filename[CARD_FILENAMELEN];
u32 time;
u32 icon_addr; /*** Offset to banner/icon data ***/
u16 icon_fmt;
u16 icon_speed;
u8 unknown1; /*** Permission key ***/
u8 unknown2; /*** Copy Counter ***/
u16 index; /*** Start block of savegame in memory card (Ignore - and throw away) ***/
u16 filesize8; /*** File size / 8192 ***/
u16 reserved02; /*** Always 0xffff ***/
u32 comment_addr;
} __attribute__((__packed__)) GCI;
#define MCDATAOFFSET 64
#endif

View File

@ -28,7 +28,6 @@
#endif
#include "mcard.h"
#include "card.h"
#include "raw.h"
#include "sdsupp.h"
#include "freetype.h"

View File

@ -16,8 +16,23 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ogc/libversion.h>
#if (_V_MAJOR_ <= 2) && (_V_MINOR_ <= 2)
#ifndef CARD_SetStatusEx
#define CARD_SetStatusEx __card_setstatusex
#endif
#ifndef CARD_GetStatusEx
#define CARD_GetStatusEx __card_getstatusex
#endif
#include "card.h"
extern s32 __card_setstatusex(s32 chn,s32 fileno,struct card_direntry *entry);
extern s32 __card_getstatusex(s32 chn,s32 fileno,struct card_direntry *entry);
s32 CARD_GetFreeBlocks(s32 chn, u16* freeblocks);
s32 CARD_GetSerialNo(s32 chn,u32 *serial1,u32 *serial2);
#else
#include <ogc/card.h>
#endif
#include "mcard.h"
#include "gci.h"
#include "freetype.h"
@ -65,7 +80,7 @@ static int cardcount = 0;
static u8 permission;
s32 memsize, sectsize;
GCI gci;
card_direntry gci;
//The following code is made by Ralf at GSCentral forums (gscentral.org)
//http://board.gscentral.org/retro-hacking/53093.htm#post188949
@ -189,31 +204,31 @@ u16 FreeBlocks(s32 chn)
void GCIMakeHeader()
{
/*** Clear out the cgi header ***/
memset(&gci, 0xff, sizeof(GCI) );
memset(&gci, 0xff, sizeof(card_direntry) );
/*** Populate ***/
memcpy(&gci.gamecode, &CardStatus.gamecode, 4);
memcpy(&gci.company, &CardStatus.company, 2);
gci.banner_fmt = CardStatus.banner_fmt;
memcpy(&gci.filename, &CardStatus.filename, CARD_FILENAMELEN);
gci.time = CardStatus.time;
gci.last_modified = CardStatus.time;
gci.icon_addr = CardStatus.icon_addr;
gci.icon_fmt = CardStatus.icon_fmt;
gci.icon_speed = CardStatus.icon_speed;
/*** Permission key has to be gotten separately. Make it 0 for normal privileges ***/
gci.unknown1 = permission;
gci.permission = permission;
/*** Who cares about copy counter ***/
gci.unknown2 = 0;
gci.copy_times = 0;
/*** Block index does not matter, it won't be restored at the same spot ***/
gci.index = 32;
gci.block = 32;
gci.filesize8 = (CardStatus.len / 8192);
gci.length = (CardStatus.len / 8192);
gci.comment_addr = CardStatus.comment_addr;
/*** Copy to head of buffer ***/
memcpy(FileBuffer, &gci, sizeof(GCI));
memcpy(FileBuffer, &gci, sizeof(card_direntry));
}
/****************************************************************************
@ -225,18 +240,18 @@ void ExtractGCIHeader()
{
/*** Clear out the status ***/
memset(&CardStatus, 0, sizeof(card_stat));
memcpy(&gci, FileBuffer, sizeof(GCI));
memcpy(&gci, FileBuffer, sizeof(card_direntry));
memcpy(&CardStatus.gamecode, &gci.gamecode, 4);
memcpy(&CardStatus.company, &gci.company, 2);
CardStatus.banner_fmt = gci.banner_fmt;
memcpy(&CardStatus.filename, &gci.filename, CARD_FILENAMELEN);
CardStatus.time = gci.time;
CardStatus.time = gci.last_modified;
CardStatus.icon_addr = gci.icon_addr;
CardStatus.icon_fmt = gci.icon_fmt;
CardStatus.icon_speed = gci.icon_speed;
permission = gci.unknown1;
CardStatus.len = gci.filesize8 * 8192;
permission = gci.permission;
CardStatus.len = gci.length * 8192;
CardStatus.comment_addr = gci.comment_addr;
}
@ -379,10 +394,10 @@ int CardReadFileHeader (int slot, int id)
GCIMakeHeader();
#else
//get directory entry (same as gci header, but with all the data)
memset(&gci,0,sizeof(GCI));
__card_getstatusex(slot,CardFile.filenum,&gci);
memset(&gci,0,sizeof(card_direntry));
CARD_GetStatusEx(slot,CardFile.filenum,&gci);
/*** Copy to head of buffer ***/
memcpy(FileBuffer, &gci, sizeof(GCI));
memcpy(FileBuffer, &gci, sizeof(card_direntry));
#endif
/*** Copy the file contents to the buffer ***/
@ -568,10 +583,10 @@ int CardReadFile (int slot, int id)
GCIMakeHeader();
#else
//get directory entry (same as gci header, but with all the data)
memset(&gci,0,sizeof(GCI));
__card_getstatusex(slot,CardFile.filenum,&gci);
memset(&gci,0,sizeof(card_direntry));
CARD_GetStatusEx(slot,CardFile.filenum,&gci);
/*** Copy to head of buffer ***/
memcpy(FileBuffer, &gci, sizeof(GCI));
memcpy(FileBuffer, &gci, sizeof(card_direntry));
#endif
/*** Copy the file contents to the buffer ***/
@ -619,7 +634,7 @@ int CardWriteFile (int slot)
memcpy(company, &gci.company, 2);
memcpy(gamecode, &gci.gamecode, 4);
memcpy(filename, &gci.filename, CARD_FILENAMELEN);
filelen = gci.filesize8 * 8192;
filelen = gci.length * 8192;
/*** Mount the card ***/
err = MountCard(slot);
@ -732,7 +747,7 @@ tryagain:
//For some reason this sets the file to Move->allowed, Copy->not allowed, Public file instead of the actual permission value
CARD_SetAttributes(slot, CardFile.filenum, &permission);
#else
__card_setstatusex(slot, CardFile.filenum, &gci);
CARD_SetStatusEx(slot, CardFile.filenum, &gci);
#endif
CARD_Close (&CardFile);

View File

@ -8,9 +8,32 @@
#include <sys/dir.h>
#include <dirent.h>
#include <ogcsys.h>
#include <ogc/libversion.h>
#if (_V_MAJOR_ <= 2) && (_V_MINOR_ <= 2)
#ifndef ogc_card_sync
#define ogc_card_sync __card_sync
#endif
#ifndef ogc_card_read
#define ogc_card_read __card_read
#endif
#ifndef ogc_card_sectorerase
#define ogc_card_sectorerase __card_sectorerase
#endif
#ifndef ogc_card_write
#define ogc_card_write __card_write
#endif
#include "card.h"
extern s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
extern s32 __card_sectorerase(s32 chn,u32 sector,cardcallback callback);
extern s32 __card_sync(s32 chn);
extern s32 __card_read(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
s32 CARD_GetFreeBlocks(s32 chn, u16* freeblocks);
s32 CARD_GetSerialNo(s32 chn,u32 *serial1,u32 *serial2);
#else
#include <ogc/card.h>
#endif
#include "sdsupp.h"
#include "card.h"
#include "mcard.h"
#include "gci.h"
#include "freetype.h"
@ -37,6 +60,12 @@ extern syssram* __SYS_LockSram();
extern syssramex* __SYS_LockSramEx();
extern u32 __SYS_UnlockSram(u32 write);
extern u32 __SYS_UnlockSramEx(u32 write);
#if (_V_MAJOR_ >= 2) && (_V_MINOR_ >= 3)
extern s32 ogc_card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
extern s32 ogc_card_sectorerase(s32 chn,u32 sector,cardcallback callback);
extern s32 ogc_card_sync(s32 chn);
extern s32 ogc_card_read(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
#endif
syssramex *sramex;
u8 imageserial[12];
@ -139,7 +168,7 @@ u64 Card_SerialNo(s32 slot)
if( (err != 0) || current_block >= 1)
break;
DCInvalidateRange(CardBuffer+SectorSize*current_block,SectorSize);
err = __card_read(slot,0,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
err = ogc_card_read(slot,0,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
if(err == 0)
{
while(read_data == 0)
@ -290,7 +319,7 @@ s8 BackupRawImage(s32 slot, s32 *bytes_writen )
if( (err != 0) || current_block >= BlockCount)
break;
DCInvalidateRange(CardBuffer+SectorSize*current_block,SectorSize);
err = __card_read(slot,SectorSize*current_block,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
err = ogc_card_read(slot,SectorSize*current_block,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
if(err == 0)
{
while(read_data == 0)
@ -481,25 +510,25 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
//DCStoreRange is called in card.c before actual writing to the card
DCStoreRange(CardBuffer+writen,write_len);
if(writen == 0 || !(writen%SectorSize)){
//s32 __card_sectorerase(s32 chn,u32 sector,cardcallback callback);
err = __card_sectorerase(slot,writen, _erase_callback);
//s32 ogc_card_sectorerase(s32 chn,u32 sector,cardcallback callback);
err = ogc_card_sectorerase(slot,writen, _erase_callback);
if(err == 0)
{
while(erase_data == 0)
usleep(1*1000); //sleep untill the erase is done which sadly takes alot longer then read
__card_sync(slot);
ogc_card_sync(slot);
#ifdef DEBUGRAW
//Check if the sector was erased (all set to 0).
//Some unofficial memory cards apparently don't erase sectors when using __card_sectorerase(),
//instead they can directly properly store the data calling just __card_write(),
//Some unofficial memory cards apparently don't erase sectors when using ogc_card_sectorerase(),
//instead they can directly properly store the data calling just ogc_card_write(),
//so the following check will always fail, preventing restore for those cards, so I'm disabling
//it and relying only on the __card_read() check done after writing the data.
//it and relying only on the ogc_card_read() check done after writing the data.
/*
memset(CheckBuffer,0,write_len);
DCInvalidateRange(CheckBuffer,write_len);
read_data = 0;
err = __card_read(slot,writen,write_len,CheckBuffer,_read_callback);
err = ogc_card_read(slot,writen,write_len,CheckBuffer,_read_callback);
while(read_data == 0)
usleep(1*1000);
@ -556,21 +585,21 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
return -1;
}
}
//s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback)
err = __card_write(slot,writen,write_len,CardBuffer+writen,_write_callback);
//s32 ogc_card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback)
err = ogc_card_write(slot,writen,write_len,CardBuffer+writen,_write_callback);
if(err == 0)
{
while(write_data == 0)
usleep(1*1000); //sleep untill the write is done which sadly takes alot longer then read
__card_sync(slot);
ogc_card_sync(slot);
#ifdef DEBUGRAW
//Check the written data against the buffer
memset(CheckBuffer,0,write_len);
DCInvalidateRange(CheckBuffer,write_len);
read_data = 0;
//err = __card_read(slot,SectorSize*current_block,SectorSize,CheckBuffer,_read_callback);
err = __card_read(slot,writen,write_len,CheckBuffer,_read_callback);
//err = ogc_card_read(slot,SectorSize*current_block,SectorSize,CheckBuffer,_read_callback);
err = ogc_card_read(slot,writen,write_len,CheckBuffer,_read_callback);
while(read_data == 0)
usleep(1*1000);

View File

@ -7,7 +7,6 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//#include <sdcard.h>
#include <sys/dir.h>
#include <dirent.h>
@ -15,7 +14,6 @@
#include "freetype.h"
#include "gci.h"
#include "mcard.h"
#include "card.h"
#include "raw.h"
#define PAGESIZE 20
@ -44,7 +42,7 @@ extern int lasticon;
extern u8 filelist[1024][1024];
extern u32 maxfile;
extern GCI gci;
extern card_direntry gci;
extern int OFFSET;
extern u8 currFolder[260];
@ -71,13 +69,13 @@ int SDSaveMCImage ()
int bytesToWrite = 0;
//sd_file *handle;
FILE *handle;
GCI thisgci;
card_direntry thisgci;
int check;
int filenumber = 0;
int retries = 0;
/*** Make a copy of the Card Dir ***/
memcpy (&thisgci, FileBuffer, sizeof (GCI));
memcpy (&thisgci, FileBuffer, sizeof (card_direntry));
memset( tfile, 0, 40 );
company[2] = 0;
gamecode[4] = 0;
@ -127,7 +125,7 @@ int SDSaveMCImage ()
}
}
bytesToWrite = (thisgci.filesize8 * 8192) + MCDATAOFFSET;
bytesToWrite = (thisgci.length * 8192) + MCDATAOFFSET;
//SDCARD_WriteFile (handle, FileBuffer, bytesToWrite);
//SDCARD_CloseFile (handle);
fwrite (FileBuffer , 1 , bytesToWrite , handle );
@ -338,9 +336,9 @@ int SDLoadMCImageHeader(char *sdfilename)
fseek(handle, OFFSET, SEEK_SET);
/*** Read the file header ***/
fread (FileBuffer,1,sizeof(GCI),handle);
fread (FileBuffer,1,sizeof(card_direntry),handle);
u16 length = (bytesToRead - OFFSET - sizeof(GCI)) / 0x2000;
u16 length = (bytesToRead - OFFSET - sizeof(card_direntry)) / 0x2000;
switch(OFFSET)
{
case 0x110:
@ -393,8 +391,8 @@ int SDLoadMCImageHeader(char *sdfilename)
GCIMakeHeader();
#else
//Let's get the full header as is, instead of populating it...
memset(&gci, 0xff, sizeof(GCI)); /*** Clear out the cgi header ***/
memcpy (&gci, FileBuffer, sizeof (GCI));
memset(&gci, 0xff, sizeof(card_direntry)); /*** Clear out the cgi header ***/
memcpy (&gci, FileBuffer, sizeof (card_direntry));
#endif
/***