/**************************************************************************** * MountCard * * Mounts the memory card in the given slot. * CARD_Mount is called for a maximum of 10 tries * Returns the result of the last attempted CARD_Mount command. ***************************************************************************/ int MountCard(int cslot) { s32 ret = -1; int tries = 0; int isMounted; // Mount the card, try several times as they are tricky while ( (tries < 10) && (ret < 0)) { /*** We already initialized the Memory Card subsystem with CARD_Init() in select_memcard_slot(). Let's reset the EXI subsystem, just to make sure we have no problems mounting the card ***/ EXI_ProbeReset(); CARD_Init (NULL, NULL); //Ensure we start in show all files mode CARD_SetCompany(NULL); CARD_SetGamecode(NULL); /*** Mount the card ***/ ret = CARD_Mount (cslot, SysArea, card_removed); if (ret >= 0) break; VIDEO_WaitVSync (); tries++; } /*** Make sure the card is really mounted ***/ isMounted = CARD_ProbeEx(cslot, &memsize, §size); if (memsize > 0 && sectsize > 0)//then we really mounted de card { return isMounted; } /*** If this point is reached, something went wrong ***/ CARD_Unmount(cslot); return ret; }
/**************************************************************************** * 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_deleteFile(file_handle* file) { int slot = (!strncmp((const char*)initial_CARDB.name, file->name, 7)); char *filename = getRelativeName(file->name); card_dir* cd = (card_dir*)&file->other; CARD_SetCompany((const char*)cd->company); CARD_SetGamecode((const char*)cd->gamecode); print_gecko("Deleting: %s from slot %i\r\n", filename, slot); int ret = CARD_DeleteEntry(slot, cd); if(ret != CARD_ERROR_READY) { uiDrawObj_t *msgBox = DrawMessageBox(D_FAIL,cardError(ret)); DrawPublish(msgBox); wait_press_A(); DrawDispose(msgBox); } return ret; }
// 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; }
// This is only called where length = file.size int deviceHandler_CARD_readFile(file_handle* file, void* buffer, unsigned int length){ unsigned int slot = file->fileBase>>24, ret = 0, file_no = file->fileBase&0xFFFFFF; void *dst = buffer; // Get the sector size u32 SectorSize = 0; CARD_GetSectorSize (slot, &SectorSize); // Create the .gci header card_stat CardStat; GCI gci; CARD_GetStatus(slot,file_no,&CardStat); memset(&gci, 0xFF, sizeof(GCI)); /*** Populate the GCI ***/ memcpy(&gci.gamecode, &CardStat.gamecode, 4); memcpy(&gci.company, &CardStat.company, 2); gci.banner_fmt = CardStat.banner_fmt; memcpy(&gci.filename, &CardStat.filename, 0x20); gci.time = CardStat.time; gci.icon_addr = CardStat.icon_addr; gci.icon_fmt = CardStat.icon_fmt; gci.icon_speed = CardStat.icon_speed; gci.unknown1 = gci.unknown2 = 0; gci.index = 32; gci.filesize8 = (CardStat.len / 8192); gci.comment_addr = CardStat.comment_addr; memcpy(dst, &gci, sizeof(GCI)); dst+= sizeof(GCI); // Re-init the card with the original file gamecode & company char game_code[16]; memcpy(&game_code[0],&gci.gamecode, 4); game_code[4] = 0; CARD_SetGamecode((const char *)&game_code[0]); memcpy(&game_code[0],&gci.company, 2); game_code[2] = 0; CARD_SetCompany((const char *)&game_code[0]); // Use the original file name char file_name[CARD_FILENAMELEN]; memset(&file_name[0],0,CARD_FILENAMELEN); memcpy(&file_name[0], file->name,strlen(file->name)-4); print_gecko("Try to open: [%s]\r\n",&file_name[0]); // Read the actual file data now char *read_buffer = NULL; card_file *memcard_file = NULL; memcard_file = (card_file*)memalign(32,sizeof(card_file)); if(!memcard_file) { return -2; } memset(memcard_file, 0, sizeof(card_file)); // Open the Entry if((ret = CARD_Open(slot, (const char*)&file_name[0], memcard_file)) != CARD_ERROR_NOFILE){ /* Allocate the read buffer */ u32 readSize = ((memcard_file->len % SectorSize) != 0) ? ((memcard_file->len/SectorSize)+1) * SectorSize : memcard_file->len; read_buffer = memalign(32,SectorSize); if(!read_buffer) { free(memcard_file); return -2; } print_gecko("Reading: [%i] bytes\r\n",readSize); /* Read the file */ int i = 0; for(i=0;i<(readSize/SectorSize);i++) { ret = CARD_Read(memcard_file,read_buffer, SectorSize, i*SectorSize); if(!ret) { memcpy(dst,read_buffer,(i==(readSize/SectorSize)-1) ? (memcard_file->len % SectorSize):SectorSize); } dst+=SectorSize; print_gecko("Read: [%i] bytes ret [%i]\r\n",SectorSize,ret); } } else { print_gecko("ret: [%i]\r\n",ret); } CARD_Close(memcard_file); free(read_buffer); free(memcard_file); return !ret ? length : ret; }
void MC_DeleteMode(int slot) { int memitems, err; int selected = 0; int erase; displaypath = 0; clearRightPane(); DrawText(386,130,"D e l e t e M o d e"); DrawText(386,134,"_____________________"); char msg[1024]; writeStatusBar("Reading memory card... ", ""); /*** Get the directory listing from the memory card ***/ memitems = CardGetDirectory (slot); setfontsize (14); writeStatusBar("Choose a file with UP button or DOWN button ", "Press A button to delete ") ; /*** If it's a blank card, get out of here ***/ if (!memitems) { WaitPrompt ("No saved games to delete !"); } else { while(1) { // TODO: implement showselector selected = ShowSelector(1); if (cancel) { WaitPrompt ("Delete action cancelled !"); return; } //0 = Z or 2 was pressed -> delete the file erase = WaitPromptChoiceAZ("Are you sure you want to delete the file?", "Delete", "Cancel"); if (!erase) { // selected = 1; /*** Delete the file ***/ sprintf(msg, "Deleting \"%s\"", CardList[selected].filename); writeStatusBar(msg,""); //WaitPrompt(msg); /*** Try to mount the card ***/ err = MountCard(slot); if (err < 0) { WaitCardError("MCDel Mount", err); return; /*** Unable to mount the card ***/ } /*** Initialise for this company & gamecode ***/ CARD_SetCompany(CardList[selected].company); CARD_SetGamecode(CardList[selected].gamecode); err = CARD_Delete(slot, (char *) &CardList[selected].filename); if (err < 0) { WaitCardError("MCDel", err); } else { WaitPrompt("Delete complete"); } CARD_Unmount(slot); return; } offsetchanged = true; } } }
/**************************************************************************** * 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; }
/**************************************************************************** * CardReadFile * * Retrieve a file from the previously populated list. * Place in filebuffer space, for collection by SMB write. ****************************************************************************/ int CardReadFile (int slot, int id) { int bytesdone = 0; int err; u32 SectorSize; char company[4]; char gamecode[6]; int filesize; if (id >= cardcount) { WaitPrompt("Bad id"); return 0; /*** Bad id ***/ } /*** Clear the work buffers ***/ memset (FileBuffer, 0, MAXFILEBUFFER); memset (SysArea, 0, CARD_WORKAREA); //add null char company[2] = gamecode[4] = 0; memcpy (company, &CardList[id].company, 2); memcpy (gamecode, &CardList[id].gamecode, 4); /*** Mount the card ***/ err = MountCard(slot); if (err < 0) { WaitCardError("CardMount", err); return 0; /*** Unable to mount the card ***/ } /*** Retrieve sector size ***/ CARD_GetSectorSize (slot, &SectorSize); /*** Initialise for this company & gamecode ***/ CARD_SetCompany(company); CARD_SetGamecode(gamecode); /*** Open the file ***/ err = CARD_Open (slot, (char *) &CardList[id].filename, &CardFile); if (err < 0) { CARD_Unmount (slot); WaitCardError("CardOpen", err); return 0; } #ifdef STATUSOGC /*** Get card status info ***/ CARD_GetStatus (slot, CardFile.filenum, &CardStatus); CARD_GetAttributes(slot,CardFile.filenum, &permission); 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); /*** Copy to head of buffer ***/ memcpy(FileBuffer, &gci, sizeof(GCI)); #endif /*** Copy the file contents to the buffer ***/ filesize = CardFile.len; while (bytesdone < filesize) { CARD_Read (&CardFile, FileBuffer + MCDATAOFFSET + bytesdone, SectorSize, bytesdone); bytesdone += SectorSize; } /*** Close the file ***/ CARD_Close (&CardFile); /*** Unmount the card ***/ CARD_Unmount (slot); return filesize + MCDATAOFFSET; }
//TODO: get icon and banner settings int CardReadFileHeader (int slot, int id) { int bytesdone = 0; int err; u32 SectorSize; char company[4]; char gamecode[6]; int filesize; int i; u16 check_fmt, check_speed; if (id >= cardcount) { WaitPrompt("Bad id"); return 0; /*** Bad id ***/ } /*** Clear the work buffers ***/ memset (FileBuffer, 0, MAXFILEBUFFER); memset (CommentBuffer, 0, 64); memset (SysArea, 0, CARD_WORKAREA); //add null char company[2] = gamecode[4] = 0; memcpy (company, &CardList[id].company, 2); memcpy (gamecode, &CardList[id].gamecode, 4); /*** Mount the card ***/ err = MountCard(slot); if (err < 0) { WaitCardError("CardMount", err); return 0; /*** Unable to mount the card ***/ } /*** Retrieve sector size ***/ CARD_GetSectorSize (slot, &SectorSize); /*** Initialise for this company & gamecode ***/ CARD_SetCompany((const char*)company); CARD_SetGamecode((const char*)gamecode); /*** Open the file ***/ err = CARD_Open (slot, (char *) &CardList[id].filename, &CardFile); if (err < 0) { CARD_Unmount (slot); WaitCardError("CardOpen", err); return 0; } #ifdef STATUSOGC /*** Get card status info ***/ CARD_GetStatus (slot, CardFile.filenum, &CardStatus); CARD_GetAttributes(slot,CardFile.filenum, &permission); 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); /*** Copy to head of buffer ***/ memcpy(FileBuffer, &gci, sizeof(GCI)); #endif /*** Copy the file contents to the buffer ***/ filesize = CardFile.len; while (bytesdone < filesize) { CARD_Read (&CardFile, FileBuffer + MCDATAOFFSET + bytesdone, SectorSize, bytesdone); bytesdone += SectorSize; } /*** Get the Banner/Icon Data from the memory card file. Very specific if/else setup to minimize data copies. ***/ u8* offset = FileBuffer + MCDATAOFFSET + gci.icon_addr; /*** Get the Banner/Icon Data from the save file ***/ if ((gci.banner_fmt&CARD_BANNER_MASK) == CARD_BANNER_RGB) { //RGB banners are 96*32*2 in size memcpy(bannerdata, offset, 6144); offset += 6144; } else if ((gci.banner_fmt&CARD_BANNER_MASK) == CARD_BANNER_CI) { memcpy(bannerdataCI, offset, 3072); offset += 3072; memcpy(tlutbanner, offset, 512); offset += 512; } //Icon data int shared_pal = 0; lastframe = 0; numicons = 0; int j =0; i=0; int current_icon = 0; for (current_icon=0;i<CARD_MAXICONS;++current_icon){ //no need to clear all values since we will only use the ones until lasticon frametable[current_icon] = 0; iconindex[current_icon] = 0; //Animation speed is mandatory to be set even for a single icon //When a speed is 0 there are no more icons //Some games may have bits set after the "blank icon" both in //speed (Baten Kaitos) and format (Wario Ware Inc.) bytes, which are just garbage if (!SDCARD_GetIconSpeed(gci.icon_speed,current_icon)){ break; }else {//We've got a frame lastframe+=SDCARD_GetIconSpeed(gci.icon_speed,current_icon)*4;//Count the total frames frametable[current_icon]=lastframe; //Store the end frame of the icon if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) != 0) { //count the number of real icons numicons++; iconindex[current_icon]=current_icon; //Map the icon //CI with shared palette if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) == 1) { memcpy(icondata[current_icon], offset, 1024); offset += 1024; shared_pal = 1; } //CI with palette after the icon else if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) == 3) { memcpy(icondata[current_icon], offset, 1024); offset += 1024; memcpy(tlut[current_icon], offset, 512); offset += 512; } //RGB 16 bit icon else if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) == 2) { memcpy(icondataRGB[current_icon], offset, 2048); offset += 2048; } }else { //Get next real icon for(j=current_icon;j<CARD_MAXICONS;++j){ if (SDCARD_GetIconFmt(gci.icon_fmt,j) != 0) { iconindex[current_icon]=j; //Map blank frame to next real icon break; } } } } } lasticon = current_icon-1; //Now get icon indexes for ping-pong style icons if (SDCARD_GetIconAnim(gci.banner_fmt) == CARD_ANIM_BOUNCE && current_icon>1) //We need at least 3 icons { j=current_icon; for (i = current_icon-2; 0 < i; --i, ++j) { lastframe += SDCARD_GetIconSpeed(gci.icon_speed,i)*4; frametable[j] = lastframe; iconindex[j] = iconindex[i]; } lasticon = j-1; } //Get the shared palette if (shared_pal) memcpy(tlut[8], offset, 512); /*** Get the comment (two 32 byte strings) into buffer ***/ memcpy(CommentBuffer, FileBuffer + MCDATAOFFSET + gci.comment_addr, 64); /*** Close the file ***/ CARD_Close (&CardFile); /*** Unmount the card ***/ CARD_Unmount (slot); return filesize + MCDATAOFFSET; }
// This function should always be called for the FULL length cause CARD is lame like that. s32 deviceHandler_CARD_writeFile(file_handle* file, void* data, u32 length) { if(gciInfo == NULL) { // Swiss ID for this CARD_SetGameAndCompany(); } else { // Game specific char company[4], gamecode[8]; memset(company, 0, 4); memset(gamecode, 0, 8); memcpy(gamecode, gciInfo->gamecode, 4); memcpy(company, gciInfo->company, 2); CARD_SetCompany(company); CARD_SetGamecode(gamecode); } card_file cardfile; unsigned int slot = (!strncmp((const char*)initial_CARDB.name, file->name, 7)), ret = 0; unsigned int adj_length = (length % 8192 == 0 ? length : (length + (8192-length%8192)))+8192; char *filename = NULL; char fname[CARD_FILENAMELEN+1]; if(gciInfo != NULL) { memset(fname, 0, CARD_FILENAMELEN+1); memcpy(fname, gciInfo->filename, CARD_FILENAMELEN); filename = &fname[0]; adj_length = gciInfo->filesize8*8192; } else { filename = getRelativeName(file->name); } // Open the file based on the slot & file name ret = CARD_Open(slot,filename, &cardfile); print_gecko("Tried to open: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); if(ret == CARD_ERROR_NOFILE) { // If the file doesn't exist, create it. ret = CARD_Create(slot, filename,adj_length,&cardfile); print_gecko("Tried to create: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); if(ret != CARD_ERROR_READY) { return ret; } ret = CARD_Open(slot,filename, &cardfile); print_gecko("Tried to open after create: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); } if(ret != CARD_ERROR_READY) { // Something went wrong return -1; } // Write the icon, comment, etc. time_t gc_time = time (NULL); char *tmpBuffer = memalign(32,adj_length); memset(tmpBuffer,0,adj_length); if(gciInfo == NULL) { strcpy(tmpBuffer, filename); strcpy(tmpBuffer+0x20, ctime (&gc_time)); memcpy(tmpBuffer+0x40, gamecube_rgb, sizeof(gamecube_rgb)); // Copy icon memcpy(tmpBuffer+0x2000, data, length); // Copy data } else { data+=sizeof(GCI); memcpy(tmpBuffer, data, length); // Copy data } // The file exists by now, write at offset. int amount_written = 0; while(amount_written != adj_length) { ret = CARD_Write(&cardfile, tmpBuffer+amount_written, card_sectorsize[slot], file->offset); file->offset += card_sectorsize[slot]; amount_written += card_sectorsize[slot]; print_gecko("Tried to write: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); if(ret != CARD_ERROR_READY) break; } card_stat cardstat; if(gciInfo == NULL) { // Swiss memset(&cardstat, 0, sizeof(card_stat)); memcpy(&cardstat.filename, filename, CARD_FILENAMELEN-1); cardstat.time = gc_time; cardstat.comment_addr = 0; cardstat.icon_addr = 0x40; cardstat.icon_speed = CARD_SPEED_FAST; cardstat.banner_fmt = CARD_BANNER_NONE; cardstat.icon_fmt = CARD_ICON_RGB; } else { // Info is coming from a GCI cardstat.banner_fmt = gciInfo->banner_fmt; cardstat.time = gciInfo->time; cardstat.icon_addr = gciInfo->icon_addr; cardstat.icon_fmt = gciInfo->icon_fmt; cardstat.icon_speed = gciInfo->icon_speed; cardstat.comment_addr = gciInfo->comment_addr; } CARD_SetStatus (slot, cardfile.filenum, &cardstat); free(tmpBuffer); CARD_Close(&cardfile); return ret == CARD_ERROR_READY ? length : ret; }
s32 deviceHandler_CARD_readFile(file_handle* file, void* buffer, u32 length){ card_file cardfile; void *dst = buffer; card_dir* cd = (card_dir*)&file->other; char *filename = getRelativeName(file->name); unsigned int slot = (!strncmp((const char*)initial_CARDB.name, file->name, 7)), ret = 0; if(cd->company[0] == '\0' && cd->gamecode[0] == '\0') { // Find the file we don't know about and populate this file_handle if we find it. if(!findFile(file)) { return CARD_ERROR_NOFILE; } CARD_SetCompany((const char*)cd->company); CARD_SetGamecode((const char*)cd->gamecode); } else { CARD_SetCompany((const char*)cd->company); CARD_SetGamecode((const char*)cd->gamecode); } int swissFile = !strncmp((const char*)cd->gamecode, "SWIS", 4) && !strncmp((const char*)cd->company, "S0", 2); // Open the file based on the slot & file name ret = CARD_Open(slot,filename, &cardfile); print_gecko("Tried to open: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); if(ret != CARD_ERROR_READY) return ret; u8 *read_buffer = (u8*)memalign(32,card_sectorsize[slot]); if(!read_buffer) { return -1; } /* Read from the file */ u32 amountRead = 0; // If this file was put here by swiss, then skip the first 8192 bytes if(swissFile && !isCopyGCIMode) { print_gecko("Swiss copied file detected, skipping icon\r\n"); file->offset += 8192; } if(isCopyGCIMode) { // Write out a .GCI card_stat cardstat; GCI gci; CARD_GetStatus(slot, cardfile.filenum, &cardstat); memset(&gci, 0, sizeof(GCI)); memcpy(&gci.gamecode,cd->gamecode,4); memcpy(&gci.company,cd->company,2); memcpy(&gci.filename,file->name,CARD_FILENAMELEN); gci.reserved01 = 0xFF; gci.banner_fmt = cardstat.banner_fmt; gci.time = cardstat.time; gci.icon_addr = cardstat.icon_addr; gci.icon_fmt = cardstat.icon_fmt; gci.icon_speed = cardstat.icon_speed; gci.unknown1 = cd->permissions; gci.filesize8 = cardstat.len / 8192; gci.reserved02 = 0xFFFF; gci.comment_addr = cardstat.comment_addr; memcpy(dst, &gci, sizeof(GCI)); dst+=sizeof(GCI); length-=sizeof(GCI); amountRead += sizeof(GCI); } while(length > 0 && file->offset < file->size) { int readsize = length > card_sectorsize[slot] ? card_sectorsize[slot] : length; print_gecko("Need to read: [%i] more bytes\r\n", length); if(file->offset&0x1ff) { ret = CARD_ReadUnaligned(&cardfile, read_buffer, card_sectorsize[slot], file->offset, slot); } else { ret = CARD_Read(&cardfile, read_buffer, card_sectorsize[slot], file->offset); // Sometimes reads fail the first time stupidly, retry at least once. print_gecko("Read: [%i] bytes ret [%i] from offset [%i]\r\n",card_sectorsize[slot],ret, file->offset); if(ret == CARD_ERROR_BUSY) { print_gecko("Read retry\r\n"); usleep(2000); ret = CARD_Read(&cardfile, read_buffer, card_sectorsize[slot], file->offset); } } if(ret == CARD_ERROR_READY) memcpy(dst,read_buffer,readsize); else return ret; dst+=readsize; file->offset += readsize; length -= readsize; amountRead += readsize; } // For swiss adjusted files, don't trail off the end. if(swissFile && length != 0) { amountRead+= length; } DCFlushRange(dst, amountRead); CARD_Close(&cardfile); free(read_buffer); return amountRead; }
//--------------------------------------------------------------------------------- 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; }