/**************************************************************************** * CardFileExists * * Wrapper to search through the files on the card. * Returns TRUE if found. ****************************************************************************/ static int CardFileExists (char *filename, u8 slot) { int CardError = CARD_FindFirst (slot, &CardDir, TRUE); while (CardError != CARD_ERROR_NOFILE) { CardError = CARD_FindNext (&CardDir); if (strcmp ((char *) CardDir.filename, filename) == 0) return 1; } return 0; }
int deviceHandler_CARD_readDir(file_handle* ffile, file_handle** dir, unsigned int type){ int num_entries = 1, ret = 0, i = 1, slot = ffile->fileBase>>24; card_dir *memcard_dir = NULL; if(!card_init[slot]) { //if some error ret = initialize_card(slot); if(ret != CARD_ERROR_READY) { return -1; //fail } } memcard_dir = (card_dir*)memalign(32,sizeof(card_dir)); memset(memcard_dir, 0, sizeof(card_dir)); /* Convert the Memory Card "file" data to fileBrowser_files */ *dir = malloc( num_entries * sizeof(file_handle) ); // Virtual Entry for entire card. memset(&(*dir)[0], 0, sizeof(file_handle)); sprintf((*dir)[0].name,"RAW Image"); (*dir)[0].fileAttrib = IS_SPECIAL; (*dir)[0].fileBase = ffile->fileBase; int usedSpace = 0; ret = CARD_FindFirst (slot, memcard_dir, true); while (CARD_ERROR_NOFILE != ret) { // Make sure we have room for this one if(i == num_entries){ ++num_entries; *dir = realloc( *dir, num_entries * sizeof(file_handle) ); } memset(&(*dir)[i], 0, sizeof(file_handle)); strcpy( (*dir)[i].name, (char*)memcard_dir->filename); (*dir)[i].name[CARD_FILENAMELEN] = '\0'; strcat( (*dir)[i].name, ".gci"); (*dir)[i].name[CARD_FILENAMELEN+4] = '\0'; (*dir)[i].fileAttrib = IS_FILE; (*dir)[i].size = memcard_dir->filelen + sizeof(GCI); (*dir)[i].fileBase = ffile->fileBase | (memcard_dir->fileno & 0xFFFFFF); ret = CARD_FindNext (memcard_dir); ++i; usedSpace += memcard_dir->filelen; } free(memcard_dir); usedSpace >>= 10; initial_CARD_info.freeSpaceInKB = initial_CARD_info.totalSpaceInKB-usedSpace; return num_entries; }
/**************************************************************************** * ParseMCDirectory * * Parses a list of all files on the specified memory card ***************************************************************************/ int ParseMCDirectory (int slot) { card_dir CardDir; int CardError; int entryNum = 0; // Try to mount the card CardError = MountMC(slot, NOTSILENT); if (CardError == 0) { CardError = CARD_FindFirst (slot, &CardDir, TRUE); while (CardError != CARD_ERROR_NOFILE) { BROWSERENTRY * newBrowserList = (BROWSERENTRY *)realloc(browserList, (entryNum+1) * sizeof(BROWSERENTRY)); if(!newBrowserList) // failed to allocate required memory { ResetBrowser(); ErrorPrompt("Out of memory: too many files!"); entryNum = -1; break; } else { browserList = newBrowserList; } memset(&(browserList[entryNum]), 0, sizeof(BROWSERENTRY)); // clear the new entry strncpy(browserList[entryNum].filename, (char *)CardDir.filename, MAXJOLIET); StripExt(browserList[entryNum].displayname, browserList[entryNum].filename); // hide file extension browserList[entryNum].length = CardDir.filelen; entryNum++; CardError = CARD_FindNext (&CardDir); } CARD_Unmount(slot); } // Sort the file list qsort(browserList, entryNum, sizeof(BROWSERENTRY), FileSortCallback); CancelAction(); browser.numEntries = entryNum; return entryNum; }
/**************************************************************************** * CardGetDirectory * * Returns number of files found on a card. ****************************************************************************/ int CardGetDirectory (int slot) { int err; char company[4]; char gamecode[6]; //add null char company[2] = gamecode[4] = 0; /*** Clear the work area ***/ memset (SysArea, 0, CARD_WORKAREA); /*** Initialise the Card system, show all ***/ CARD_Init(NULL, NULL); /*** Try to mount the card ***/ err = MountCard(slot); if (err < 0) { WaitCardError("CardMount", err); return 0; /*** Unable to mount the card ***/ } //Ensure we are in show all mode CARD_SetCompany(NULL); CARD_SetGamecode(NULL); /*** Retrieve the directory listing ***/ cardcount = 0; err = CARD_FindFirst (slot, &CardDir, true); //true means we want to showall while (err != CARD_ERROR_NOFILE) { memcpy (&CardList[cardcount], &CardDir, sizeof (card_dir)); memset (filelist[cardcount], 0, 1024); memcpy (company, &CardDir.company, 2); memcpy (gamecode, &CardDir.gamecode, 4); //This array will store what will show in left window sprintf ((char*)filelist[cardcount], "%s-%s-%s", company, gamecode, CardDir.filename); cardcount++; err = CARD_FindNext (&CardDir); } /*** Release as soon as possible ***/ CARD_Unmount (slot); maxfile = cardcount; return cardcount; }
s32 deviceHandler_CARD_readDir(file_handle* ffile, file_handle** dir, u32 type){ int num_entries = 1, ret = 0, i = 0, slot = (!strncmp((const char*)initial_CARDB.name, ffile->name, 7)); card_dir *memcard_dir = NULL; if(!card_init[slot]) { //if some error ret = initialize_card(slot); if(ret != CARD_ERROR_READY) { return -1; //fail } } CARD_SetGameAndCompany(); memcard_dir = (card_dir*)memalign(32,sizeof(card_dir)); memset(memcard_dir, 0, sizeof(card_dir)); /* Convert the Memory Card "file" data to fileBrowser_files */ *dir = malloc( num_entries * sizeof(file_handle) ); int usedSpace = 0; ret = CARD_FindFirst (slot, memcard_dir, true); while (CARD_ERROR_NOFILE != ret) { // Make sure we have room for this one if(i == num_entries){ ++num_entries; *dir = realloc( *dir, num_entries * sizeof(file_handle) ); } memset(&(*dir)[i], 0, sizeof(file_handle)); strcpy((*dir)[i].name, ffile->name); strncat((*dir)[i].name, (char*)memcard_dir->filename, CARD_FILENAMELEN); (*dir)[i].fileAttrib = IS_FILE; (*dir)[i].size = memcard_dir->filelen; memcpy( (*dir)[i].other, memcard_dir, sizeof(card_dir)); usedSpace += memcard_dir->filelen; ret = CARD_FindNext (memcard_dir); ++i; } free(memcard_dir); usedSpace >>= 10; initial_CARD_info.freeSpaceInKB = initial_CARD_info.totalSpaceInKB-usedSpace; return num_entries; }
// Finds a file based on file->name and populates file->size if found. bool findFile(file_handle* file) { unsigned int slot = (!strncmp((const char*)initial_CARDB.name, file->name, 7)), ret = 0; char *filename = getRelativeName(file->name); bool found = false; CARD_SetGameAndCompany(); card_dir* memcard_dir = (card_dir*)memalign(32,sizeof(card_dir)); memset(memcard_dir, 0, sizeof(card_dir)); ret = CARD_FindFirst (slot, memcard_dir, true); while (CARD_ERROR_NOFILE != ret && !found) { if(!strcasecmp((const char*)filename, (char*)memcard_dir->filename)) { file->size = memcard_dir->filelen; memcpy( file->other, memcard_dir, sizeof(card_dir)); found = true; } ret = CARD_FindNext (memcard_dir); } free(memcard_dir); return found; }
//--------------------------------------------------------------------------------- int main() { //--------------------------------------------------------------------------------- VIDEO_Init(); rmode = VIDEO_GetPreferredMode(NULL); PAD_Init(); xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); VIDEO_Configure(rmode); VIDEO_SetNextFramebuffer(xfb); VIDEO_SetBlack(FALSE); VIDEO_Flush(); VIDEO_WaitVSync(); if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); console_init(xfb,20,64,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*2); VIDEO_SetNextFramebuffer(xfb); printf("Memory Card Demo\n\n"); while (1) { printf("Insert A card in slot B and press A\n"); do { PAD_ScanPads(); if (PAD_ButtonsDown(0) & PAD_BUTTON_START) PSOreload(); VIDEO_WaitVSync(); } while ( !(PAD_ButtonsDown(0) & PAD_BUTTON_A)); printf("Mounting card ...\n"); CARD_Init("DEMO","00"); int SlotB_error = CARD_Mount(CARD_SLOTB, SysArea, card_removed); printf("slot B code %d\n",SlotB_error); int CardError; if (SlotB_error >= 0) { unsigned int SectorSize = 0; CARD_GetSectorSize(CARD_SLOTB,&SectorSize); printf("Sector size is %d bytes.\n\n",SectorSize); char *CardBuffer = (char *)memalign(32,SectorSize); printf("Starting directory\n"); card_dir CardDir; card_file CardFile; CardError = CARD_FindFirst(CARD_SLOTB, &CardDir, true); bool found = false; while ( CARD_ERROR_NOFILE != CardError ) { printf("%s %s %s\n",CardDir.filename,CardDir.gamecode,CardDir.company); CardError = CARD_FindNext(&CardDir); if ( 0 == strcmp (DemoFileName, (char *)CardDir.filename)) found = true; }; printf("Finished directory\n\n"); if (found) { printf("Test file contains :- \n"); CardError = CARD_Open(CARD_SLOTB ,DemoFileName,&CardFile); CARD_Read(&CardFile,CardBuffer,SectorSize,0); printf("%s\n",CardBuffer); CARD_Close(&CardFile); CARD_Delete(CARD_SLOTB,DemoFileName); } else { printf("writing test file ...\n"); CardError = CARD_Create(CARD_SLOTB ,DemoFileName,SectorSize,&CardFile); if (0 == CardError) { time_t gc_time; gc_time = time(NULL); sprintf(CardBuffer,"This text was written by MemCardDemo\nat %s\n",ctime(&gc_time)); CardError = CARD_Write(&CardFile,CardBuffer,SectorSize,0); CardError = CARD_Close(&CardFile); } } CARD_Unmount(CARD_SLOTB); free(CardBuffer); } } }
// Only accepts a .gci file int deviceHandler_CARD_writeFile(file_handle* file, void* data, unsigned int length) { card_stat CardStatus; card_dir CardDir; card_file CardFile; GCI gci; int err = 0; unsigned int SectorSize = 0, slot = file->fileBase>>24; char tmpBuf[5]; /*** Clear out the status ***/ memset(&CardStatus, 0, sizeof(card_stat)); memcpy(&gci, data, sizeof(GCI)); 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.icon_addr = gci.icon_addr; CardStatus.icon_fmt = gci.icon_fmt; CardStatus.icon_speed = gci.icon_speed; CardStatus.len = gci.filesize8 * 8192; CardStatus.comment_addr = gci.comment_addr; CARD_Init((char*)gci.gamecode,(char*)gci.company); memcpy(&tmpBuf[0],(char*)gci.gamecode,4); tmpBuf[4]='\0'; CARD_SetGamecode(&tmpBuf[0]); memcpy(&tmpBuf[0],(char*)gci.company,2); tmpBuf[2]='\0'; CARD_SetCompany(&tmpBuf[0]); err = CARD_Mount (slot, sys_area, NULL); if (err) return -1; CARD_GetSectorSize (slot, &SectorSize); /*** If this file exists, abort ***/ err = CARD_FindFirst (slot, &CardDir, false); while (err != CARD_ERROR_NOFILE){ if (strcmp ((char *) CardDir.filename, (char *)gci.filename) == 0){ /*** Found the file - abort ***/ CARD_Unmount (slot); return -2; } err = CARD_FindNext (&CardDir); } /*** Now restore the file from backup ***/ err = CARD_Create (slot, (char *) gci.filename, gci.filesize8 * 8192, &CardFile); if (err){ CARD_Unmount (slot); return -3; } /*** Now write the file data, in sector sized chunks ***/ int offset = 0; while (offset < (gci.filesize8 * 8192)){ if ((offset + SectorSize) <= (gci.filesize8 * 8192)) { CARD_Write (&CardFile, data + 0x40 + offset, SectorSize, offset); } else { CARD_Write (&CardFile, data + 0x40 + offset, ((offset + SectorSize) - (gci.filesize8 * 8192)), offset); } offset += SectorSize; } /*** Finally, update the status ***/ CARD_SetStatus (slot, CardFile.filenum, &CardStatus); CARD_Close (&CardFile); CARD_Unmount (slot); return length; }
/**************************************************************************** * CardWriteFile * * Relies on *GOOD* data being placed in the FileBuffer prior to calling. * See ReadSMBImage ****************************************************************************/ int CardWriteFile (int slot) { char company[4]; char gamecode[6]; char filename[CARD_FILENAMELEN]; int err, ret; u32 SectorSize; int offset; int written; int filelen; char txt[128]; //add null char company[2] = gamecode[4] = 0; memset (SysArea, 0, CARD_WORKAREA); memset(filename, 0, CARD_FILENAMELEN); ExtractGCIHeader(); memcpy(company, &gci.company, 2); memcpy(gamecode, &gci.gamecode, 4); memcpy(filename, &gci.filename, CARD_FILENAMELEN); filelen = gci.filesize8 * 8192; /*** Mount the card ***/ err = MountCard(slot); if (err < 0) { WaitCardError("CardMount", err); return 0; /*** Unable to mount the card ***/ } CARD_GetSectorSize (slot, &SectorSize); /*** Initialise for this company & gamecode ***/ CARD_SetCompany(company); CARD_SetGamecode(gamecode); /*** If this file exists, abort ***/ err = CARD_FindFirst (slot, &CardDir, false); while (err != CARD_ERROR_NOFILE) { if ((memcmp(CardDir.gamecode, &gamecode, 4) == 0) && (memcmp(CardDir.company, &company, 2) == 0) && (strcmp ((char *) CardDir.filename, (char *)filename) == 0)) { /*** Found the file - prompt user ***/ sprintf(txt, "Savegame %s(%s%s) already exists. Overwrite?", (char *)filename, gamecode, company); ret = WaitPromptChoice(txt, "Overwrite", "Cancel"); if (!ret){ sprintf(txt, "Are you -SURE- you want to overwrite %s?", (char *)filename); ret = WaitPromptChoiceAZ(txt, "Overwrite", "Cancel"); if(!ret){ err = CARD_Delete(slot, (char *) &filename); if (err < 0) { WaitCardError("MCDel", err); CARD_Unmount (slot); return 0; } err = CARD_FindFirst (slot, &CardDir, false); continue; } } /*** User canceled - abort ***/ CARD_Unmount (slot); WaitCardError("File already exists", err); return 0; } err = CARD_FindNext (&CardDir); } tryagain: /*** Initialise for this company & gamecode ***/ //Again just in case, as this is very important for propper restoring CARD_SetCompany(company); CARD_SetGamecode(gamecode); /*** Now restore the file from backup ***/ err = CARD_Create (slot, (char *) filename, filelen, &CardFile); if (err < 0) { if (err == CARD_ERROR_EXIST) { /*** Found the file - prompt user ***/ sprintf(txt, "File %s(%s%s) already exists. Overwrite?", (char *) filename, gamecode, company); ret = WaitPromptChoice(txt, "Overwrite", "Cancel"); if (!ret){ sprintf(txt, "Are you -SURE- you want to overwrite %s?", (char *) filename); ret = WaitPromptChoiceAZ(txt, "Overwrite", "Cancel"); if(!ret){ err = CARD_Delete(slot, (char *) &filename); if (err < 0) { WaitCardError("MCDel", err); CARD_Unmount (slot); return 0; } goto tryagain; } } } CARD_Unmount (slot); WaitCardError("CardCreate", err); return 0; } //Thanks to Ralf, validate F-zero and PSO savegames FZEROGX_MakeSaveGameValid(slot); PSO_MakeSaveGameValid(slot); /*** Now write the file data, in sector sized chunks ***/ offset = 0; while (offset < filelen) { if ((offset + SectorSize) <= filelen) { written = CARD_Write (&CardFile, FileBuffer + MCDATAOFFSET + offset + OFFSET, SectorSize, offset); } else { written = CARD_Write (&CardFile, FileBuffer + MCDATAOFFSET + offset + OFFSET, ((offset + SectorSize) - filelen), offset); } offset += SectorSize; } OFFSET = 0; #ifdef STATUSOGC /*** Finally, update the status ***/ CARD_SetStatus (slot, CardFile.filenum, &CardStatus); //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); #endif CARD_Close (&CardFile); CARD_Unmount (slot); return 1; }
//--------------------------------------------------------------------------------- int main() { //--------------------------------------------------------------------------------- VIDEO_Init(); rmode = VIDEO_GetPreferredMode(NULL); PAD_Init(); xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); VIDEO_Configure(rmode); VIDEO_SetNextFramebuffer(xfb); VIDEO_SetBlack(FALSE); VIDEO_Flush(); VIDEO_WaitVSync(); if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); console_init(xfb,20,64,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*2); VIDEO_SetNextFramebuffer(xfb); int slot = CARD_SLOTA; u32 i; int tomenu = 0; u16 buttonsDown; u8 pressed = 0; int filesize; int bytesdone = 0; while(1){ VIDEO_ClearFrameBuffer (rmode, xfb, COLOR_BLACK); listpos=0; tomenu=0; pressed = 0; printf("\x1b[2;0H"); printf("Memory Card Loader 0.2 by Suloku\n"); printf("********************************\n\n"); printf("Press A or B button to select a slot.\n"); while (1){ PAD_ScanPads(); buttonsDown=PAD_ButtonsDown(0); if (buttonsDown & PAD_BUTTON_A){ slot = CARD_SLOTA; pressed = 1;} if (buttonsDown & PAD_BUTTON_B){ slot = CARD_SLOTB; pressed = 1;} if (buttonsDown & PAD_BUTTON_START){ PSOreload();} VIDEO_WaitVSync(); if (pressed) break; } printf("Mounting card in slot %s...", (slot==0?"A":"B")); int Slot_error = MountCard(slot); printf("code %d. ",Slot_error); int CardError; if (Slot_error >= 0) { printf("Sector size is %d bytes.\n",sectsize); printf("Reading memory card files..."); card_dir CardDir; card_file CardFile; CardError = CARD_FindFirst(slot, &CardDir, true); cardcount = 0; while ( CARD_ERROR_NOFILE != CardError ) { if (strncmp ("DOLX", (char *)CardDir.gamecode, 4) == 0){ memcpy (&CardList[cardcount], &CardDir, sizeof (card_dir)); cardcount++; } CardError = CARD_FindNext(&CardDir); } printf("finished.\n\n"); if (cardcount == 0){ printf("No dol files in memory card in slot %s\n\n", (slot==0?"A":"B")); waitA(); }else{ while (1){ pressed = 0; VIDEO_ClearFrameBuffer (rmode, xfb, COLOR_BLACK); printf("\x1b[2;0H"); printf("Memory Card Loader 0.1 by Suloku\n"); printf("********************************\n\n"); printf("Dol files in memory card %s: %d\n\n", (slot==0?"A":"B"), cardcount); if (listpos!=0) printf ("/\\/\\\n"); else printf(" \n"); for (i=listpos; i<listpos+10; i++){ printf (" "); if (i==listpos) printf ("-->"); printf("%s \n",CardList[i].filename); if (i>= cardcount )break; } printf("\x1b[18;0H"); if (cardcount >=10 && listpos != cardcount-1) printf ("\\/\\/\n"); else{ printf(" \n"); } printf("\n\t\tPress B button to go back to slot select.\n\n"); while (1){ PAD_ScanPads(); buttonsDown=PAD_ButtonsDown(0); if (buttonsDown & PAD_BUTTON_UP){ listpos--; if (listpos <0) listpos = 0; pressed = 1; } if (buttonsDown & PAD_BUTTON_DOWN){ listpos++; if (listpos >= cardcount-1) listpos = cardcount-1; pressed = 1; } if (buttonsDown & PAD_BUTTON_LEFT){ listpos-=10; if (listpos <0) listpos = 0; pressed = 1; } if (buttonsDown & PAD_BUTTON_RIGHT){ listpos+=10; if (listpos >= cardcount-1) listpos = cardcount-1; pressed = 1; } if (buttonsDown & PAD_BUTTON_A){ printf("Loading %s...\n", CardList[listpos].filename); /*** Initialise for this company & gamecode ***/ //add null char company[2] = gamecode[4] = 0; memcpy (company, &CardList[listpos].company, 2); memcpy (gamecode, &CardList[listpos].gamecode, 4); CARD_SetCompany(company); CARD_SetGamecode(gamecode); CardError = CARD_Open(slot ,(char*)&CardList[listpos].filename,&CardFile); if (CardError < 0) { CARD_Unmount (slot); printf("Error %d while opening file.\n", CardError); waitA(); }else{ /*** Copy the file contents to the buffer ***/ filesize = CardFile.len; u8 *dolbuffer = (u8*) memalign(32, filesize); while (bytesdone < filesize) { CardError= CARD_Read(&CardFile, dolbuffer+bytesdone, sectsize, bytesdone); bytesdone += sectsize; } CARD_Close(&CardFile); CARD_Unmount(slot); //boot dol //This will load cli_buffer and cli_size getclifrombuffer(dolbuffer, filesize); if (cli_buffer!=NULL){ // Build a command line to pass to the DOL int argc2 = 0; char *argv2[1024]; //add a terminating null character for last argument if needed if (cli_buffer[cli_size-1] != '\0'){ cli_buffer[cli_size] = '\0'; cli_size += 1; } // CLI parse char bootpath[CARD_FILENAMELEN+10]; sprintf(bootpath, "mc%d:/%s", slot, (char*)&CardList[listpos].filename); argv2[argc2] = bootpath; argc2++; // First argument is at the beginning of the file if(cli_buffer[0] != '\r' && cli_buffer[0] != '\n') { argv2[argc2] = cli_buffer; argc2++; } // Search for the others after each newline int i; for(i = 0; i < cli_size; i++) { if(cli_buffer[i] == '\r' || cli_buffer[i] == '\n') { cli_buffer[i] = '\0'; } else if(cli_buffer[i - 1] == '\0') { argv2[argc2] = cli_buffer + i; argc2++; if(argc2 >= 1024) break; } } DOLtoARAM(dolbuffer, argc2, argc2 == 0 ? NULL : argv2); }else{ DOLtoARAM(dolbuffer, 0, NULL); } //If we get here dol was invalid if(dolbuffer != NULL) free(dolbuffer); printf("Not a valid dol file.\n"); waitA(); tomenu = 1; } pressed = 1; } if (buttonsDown & PAD_BUTTON_B){ pressed = 1;tomenu=1;} if (buttonsDown & PAD_BUTTON_START){ PSOreload();} VIDEO_WaitVSync(); if (pressed) break; } if (tomenu) break; } } CARD_Unmount(slot); }else{ printf("\n\nCan't mount card in slot %s!\n", (slot==0?"A":"B")); waitA(); } } return 0; }
void MCManage(int mode, int slot) { char mcFilename[80]; int CardError; card_dir CardDir; card_file CardFile; int SectorSize; int found = 0; int FileSize; int actualSize; int savedBytes=0; char debug[128]; CARDSLOT = slot; /*** Build the file name ***/ sprintf(mcFilename, "FCEU-%08x.fcs", iNESGameCRC32); /*** Mount the Card ***/ CARD_Init("FCEU", "00"); /*** Try for memory card in slot A ***/ CardError = CARD_Mount(CARDSLOT, SysArea, CardRemoved ); if ( CardError >= 0 ) { /*** Get card sector size ***/ CardError = CARD_GetSectorSize(CARDSLOT, &SectorSize); switch ( mode ) { case 0 : { /*** Save Game ***/ /*** Look for this file ***/ CardError = CARD_FindFirst(CARDSLOT, &CardDir, true); found = 0; card_stat CardStatus; while ( CardError != CARD_ERROR_NOFILE ) { CardError = CARD_FindNext(&CardDir); if ( strcmp(CardDir.filename, mcFilename) == 0 ) found = 1; } /*** Determine number of sectors required ***/ savedBytes = actualSize = GCFCEUSS_Save(); sprintf(debug, "Saving in MC ..."); ShowAction(debug); FileSize = ( actualSize / SectorSize ) * SectorSize; if ( actualSize % SectorSize ) FileSize += SectorSize; /*** Now write the file out ***/ if ( !found ) CardError = CARD_Create(CARDSLOT, mcFilename, FileSize, &CardFile); else CardError = CARD_Open(CARDSLOT, mcFilename, &CardFile); CARD_GetStatus( CARDSLOT, CardFile.filenum, &CardStatus); CardStatus.icon_addr = 0; CardStatus.icon_fmt = 2; CardStatus.icon_speed = 1; CardStatus.comment_addr = sizeof(saveicon); CARD_SetStatus( CARDSLOT, CardFile.filenum, &CardStatus); /*** Haha! libogc only write one block at a time! ***/ if ( CardError == 0 ) { int sbo = 0; while ( actualSize > 0 ) { CardError = CARD_Write(&CardFile, &statebuffer[sbo], SectorSize, sbo ); actualSize -= SectorSize; sbo += SectorSize; } CardError = CARD_Close(&CardFile); sprintf(debug, "Saved %d bytes successfully!", savedBytes); WaitPrompt(debug); } else WaitPrompt("Save Failed!"); CARD_Unmount(CARDSLOT); } break; /*** End save ***/ case 1: { /*** Load state ***/ /*** Look for this file ***/ CardError = CARD_FindFirst(CARDSLOT, &CardDir, true); memopen(); /*** Clear the buffer ***/ found = 0; while ( CardError != CARD_ERROR_NOFILE ) { CardError = CARD_FindNext(&CardDir); if ( strcmp(CardDir.filename, mcFilename) == 0 ) found = 1; } if ( found == 0 ) { WaitPrompt("No Save Game Found"); CARD_Unmount(CARDSLOT); return; } /*** Load the file into memory ***/ CardError = CARD_Open(CARDSLOT, mcFilename, &CardFile); CardError = CARD_Read(&CardFile, &statebuffer, SectorSize, 0); /*** Get actual size of the file ***/ memcpy(&actualSize, &statebuffer[FILESIZEOFFSET], 4); savedBytes = actualSize; int sbo = SectorSize; actualSize -= SectorSize; while( actualSize > 0 ) { CARD_Read(&CardFile, &statebuffer[sbo], SectorSize, sbo); actualSize -= SectorSize; sbo += SectorSize; } CARD_Close(&CardFile); /*** Finally, do load ***/ GCFCEUSS_Load(); CARD_Unmount(CARDSLOT); sprintf(debug, "Loaded %d bytes successfully!", savedBytes); WaitPrompt(debug); } break; /*** End load ***/ default: break; } } else { WaitPrompt("Cannot Mount Memory Card!"); } }