mirror of
https://github.com/ApacheThunder/GBA-Exploader.git
synced 2025-06-18 11:35:38 -04:00

* NorFlash menu fully disabled for Omega. Pressing L no longer causes NorFlash menu to come up while in rumble/expansion ram selection menu. * Bug with ini file setup that causes default folders to always be created despite ini file defining custom folder locations has been resolved. * Menu display for Omega now changed to Omega DE. DE is currently the only cart that will have functional saves for games.
1313 lines
27 KiB
C++
1313 lines
27 KiB
C++
#include <nds.h>
|
|
|
|
#include <fat.h>
|
|
#include <sys/iosupport.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <dirent.h>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
//#include "disc_io.h"
|
|
//#include "gba_nds_fat.h"
|
|
|
|
//#include "unicode.h"
|
|
#include "skin.h"
|
|
#include "gba_patch.h"
|
|
#include "GBA_ini.h"
|
|
#include "header_rep.h"
|
|
#include "ctrl_tbl.h"
|
|
//#include <nds/registers_alt.h>
|
|
//#include <nds/arm9/rumble.h>
|
|
|
|
#include "dsCard.h"
|
|
#include "sc_patches.h"
|
|
#include "sc_sram.h"
|
|
|
|
//#include <nds/arm9/console.h> //basic print funcionality
|
|
|
|
#define MAX_NOR 0x2000000 // 32MByte
|
|
#define MAX_NORPLUS 0x4000000 // 64MByte (3 in 1 Plus)
|
|
#define MAX_PSRAM 0x1000000 // 16MByte
|
|
#define SRAM_PAGE_SIZE 0x10000 // SRAM Page Size
|
|
#define MAX_SRAM 0x80000 // 4MBit/512KByte total SRAM
|
|
|
|
#define USE_SRAM 0x20000 // 128KByte
|
|
#define USE_SRAM_PG 48 // 0x0A030000-0A031FFF
|
|
#define USE_SRAM_PG_EZ4 11 // 0x0A008000-0A00FFFF
|
|
#define USE_SRAM_PG_EWN 10 // 0x0A020000-0A02FFFF
|
|
#define USE_SRAM_PG_EWN128 9 // 0x0A010000-0A01FFFF
|
|
#define USE_SRAM_PG_M3 6
|
|
|
|
#define USE_SRAM_NOR 16 // 0x0A010000-0A02FFFF
|
|
#define USE_SRAM_PSR 50 // 0x0A032000-0A051FFF
|
|
#define USE_SRAM_PSR_EZ4 16 // 0x0A010000-0A02FFFF
|
|
#define USE_SRAM_PSR_EWN 8 // 0x0A000000-0A01FFFF
|
|
#define USE_SRAM_PSR_M3 4
|
|
#define USE_SRAM_PSR_OMEGA 0
|
|
|
|
#define PSRAM_BUF 0x8000 // 32KB
|
|
|
|
#define poke(addr) do{(void)*(vu8*)addr;} while(0)
|
|
#define poke16(addr) do{(void)*(vu16*)addr;} while(0)
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
extern void turn_off(int cmd);
|
|
extern void dsp_bar(int mod, int per);
|
|
|
|
extern char curpath[];
|
|
extern int sortfile[];
|
|
|
|
extern struct GBA_File fs[];
|
|
extern char tbuf[];
|
|
extern u8 *rwbuf;
|
|
|
|
extern int numFiles;
|
|
extern int numGames;
|
|
|
|
extern int GBAmode;
|
|
|
|
static u32 savesize;
|
|
|
|
int carttype = 0;
|
|
bool isSuperCard = false;
|
|
bool is3in1Plus = false;
|
|
bool isOmega = false;
|
|
|
|
extern int save_sel(int mod, char *name);
|
|
extern u16 gl_ingame_RTC_open_status;
|
|
extern void SetSDControl(u16 control);
|
|
|
|
char const *Rudolph = "GBA ExpLoader by Rudolph (LocalCode v0.1)";
|
|
|
|
using namespace std;
|
|
|
|
void SetEWINRam(u8 page) {
|
|
vu32 wait;
|
|
// vu8 a;
|
|
|
|
|
|
poke(0x0A005555);
|
|
poke(0x0A002AAA);
|
|
poke(0x0A00B055);
|
|
|
|
*(vu8*)0x0A000000 = page;
|
|
|
|
for(wait = 0; wait < 15000; wait++); // 1ms
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A000000);
|
|
poke(0x0A000000);
|
|
}
|
|
|
|
|
|
int check_EWIN() {
|
|
vu32 wait;
|
|
vu8 a, a8, a9, aa, org;
|
|
|
|
for(wait = 0; wait < 15000; wait++)a = *(vu8*)(0x0A000000 + wait);
|
|
|
|
org = *(vu8*)0x0A000000;
|
|
|
|
SetEWINRam(0);
|
|
|
|
a = *(vu8*)0x0A005555;
|
|
a = *(vu8*)0x0A002AAA;
|
|
a = *(vu8*)0x0A009055;
|
|
|
|
a = *(vu8*)0x0A000000;
|
|
|
|
SetEWINRam(0x08);
|
|
|
|
a = *(vu8*)0x0A005555;
|
|
a = *(vu8*)0x0A002AAA;
|
|
a = *(vu8*)0x0A009055;
|
|
|
|
a = *(vu8*)0x0A000000;
|
|
if(a != 0xB8) {
|
|
*(vu8*)0x0A000000 = org;
|
|
return 0;
|
|
}
|
|
|
|
SetEWINRam(0x08);
|
|
a8 = *(vu8*)0x0A000600;
|
|
|
|
SetEWINRam(0x09);
|
|
a9 = *(vu8*)0x0A000600;
|
|
|
|
*(vu8*)0x0A000600 = a8 ^ 0xFF;
|
|
|
|
SetEWINRam(0x08);
|
|
a = *(vu8*)0x0A000600;
|
|
*(vu8*)0x0A000600 = a8;
|
|
|
|
if(a != a8) {
|
|
*(vu8*)0x0A000000 = org;
|
|
return 0;
|
|
}
|
|
|
|
SetEWINRam(0x09);
|
|
*(vu8*)0x0A000600 = a9;
|
|
|
|
SetEWINRam(0x0A);
|
|
aa = *(vu8*)0x0A000600;
|
|
|
|
*(vu8*)0x0A000600 = a8 ^ 0xFF;
|
|
|
|
SetEWINRam(0x08);
|
|
a = *(vu8*)0x0A000600;
|
|
*(vu8*)0x0A000600 = a8;
|
|
if(a != a8)return 2;
|
|
|
|
SetEWINRam(0x0A);
|
|
*(vu8*)0x0A000600 = aa;
|
|
|
|
SetEWINRam(0x08);
|
|
|
|
return 1;
|
|
}
|
|
|
|
bool Close_EWIN() {
|
|
vu8 a;
|
|
|
|
|
|
SetEWINRam(0x0C);
|
|
|
|
a = *(vu8*)0x0A005555;
|
|
a = *(vu8*)0x0A002AAA;
|
|
a = *(vu8*)0x0A009055;
|
|
|
|
a = *(vu8*)0x0A000000;
|
|
|
|
if(a != 0xBC)return false;
|
|
a = *(vu8*)0x0A000000;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void SetM3Ram(u8 page) {
|
|
u32 mode;
|
|
// vu16 tmp;
|
|
|
|
mode = (u32)page << 5;
|
|
|
|
// M3
|
|
|
|
poke16(0x08000000);
|
|
poke16(0x08E00002);
|
|
poke16(0x0800000E);
|
|
poke16(0x08801FFC);
|
|
poke16(0x0800104A);
|
|
poke16(0x08800612);
|
|
poke16(0x08000000);
|
|
poke16(0x08801B66);
|
|
poke16((0x08000000 + mode));
|
|
poke16(0x0800080E);
|
|
poke16(0x08000000);
|
|
|
|
// G6
|
|
poke16(0x09000000);
|
|
poke16(0x09FFFFE0);
|
|
poke16(0x09FFFFEC);
|
|
poke16(0x09FFFFEC);
|
|
poke16(0x09FFFFEC);
|
|
poke16(0x09FFFFFC);
|
|
poke16(0x09FFFFFC);
|
|
poke16(0x09FFFFFC);
|
|
poke16(0x09FFFF4A);
|
|
poke16(0x09FFFF4A);
|
|
poke16(0x09FFFF4A);
|
|
|
|
poke16((0x09800000 + (mode << 12)));
|
|
// poke16(0x09FFFFF0);
|
|
poke16(0x09FFFFE8);
|
|
}
|
|
|
|
bool _set_M3(int sw) {
|
|
vu32 wait;
|
|
// vu16 tmp;
|
|
// vu8 a;
|
|
|
|
// M3
|
|
poke16(0x08000000);
|
|
poke16(0x08E00002);
|
|
poke16(0x0800000E);
|
|
poke16(0x08801FFC);
|
|
poke16(0x0800104A);
|
|
poke16(0x08800612);
|
|
poke16(0x08000000);
|
|
poke16(0x08801B66);
|
|
if(sw == 0)poke16(0x08800004);
|
|
if(sw == 1)poke16(0x0880000C);
|
|
if(sw == 2)poke16(0x08800008);
|
|
poke16(0x0800080E);
|
|
poke16(0x08000000);
|
|
|
|
if(sw == 2) {
|
|
poke16(0x080001E4);
|
|
poke16(0x080001E4);
|
|
poke16(0x08000188);
|
|
poke16(0x08000188);
|
|
}
|
|
|
|
// G6
|
|
poke16(0x09000000);
|
|
poke16(0x09FFFFE0);
|
|
poke16(0x09FFFFEC);
|
|
poke16(0x09FFFFEC);
|
|
poke16(0x09FFFFEC);
|
|
poke16(0x09FFFFFC);
|
|
poke16(0x09FFFFFC);
|
|
poke16(0x09FFFFFC);
|
|
poke16(0x09FFFF4A);
|
|
poke16(0x09FFFF4A);
|
|
poke16(0x09FFFF4A);
|
|
|
|
if(sw == 0)poke16(0x09200004);
|
|
if(sw == 1)poke16(0x0920000C);
|
|
if(sw == 2)poke16(0x09200008);
|
|
poke16(0x09FFFFF0);
|
|
poke16(0x09FFFFE8);
|
|
|
|
// GBA Pack
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000001);
|
|
poke16(0x08000000); // tmp
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000006);
|
|
poke16(0x08000800); // tmp
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000008);
|
|
poke16(0x09000040); // tmp
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000008);
|
|
poke16(0x09000060); // tmp
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000006);
|
|
poke16(0x08000800); // tmp
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000007);
|
|
poke16(0x08000000); // tmp
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000003);
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000005);
|
|
poke16(0x08000000); // tmp
|
|
|
|
for(wait = 0; wait < 15000; wait++); // 1ms
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A00000A);
|
|
poke16(0x08000000); // tmp
|
|
|
|
poke(0x0A000000);
|
|
poke(0x0A009999);
|
|
poke(0x0A009999);
|
|
poke(0x0A006666);
|
|
poke(0x0A006666);
|
|
poke(0x0A000003);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Close_M3() {
|
|
_set_M3(0);
|
|
return true;
|
|
}
|
|
|
|
int check_M3() {
|
|
vu16 tmp;
|
|
|
|
_set_M3(1);
|
|
tmp = *(vu16*)0x08000000;
|
|
|
|
*(vu16*)0x08000000 = 0x0123;
|
|
if(*(vu16*)0x08000000 == 0x0123) {
|
|
Close_M3();
|
|
*(vu16*)0x08000000 = 0xABCD;
|
|
if(*(vu16*)0x08000000 != 0xABCD) {
|
|
_set_M3(1);
|
|
*(vu16*)0x08000000 = tmp;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
*(vu16*)0x08000000 = tmp;
|
|
return false;
|
|
}
|
|
|
|
|
|
static bool CheckForSuperCard() {
|
|
if (CheckSuperCardID() == 0x227E0000) {
|
|
carttype = 6;
|
|
is3in1Plus = false;
|
|
isSuperCard = true;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool CheckForOmega() { // EZFlash Omega
|
|
SetRompage(0x8002);
|
|
if (CheckOmegaID() == 0x227EEA00) {
|
|
carttype = 1;
|
|
is3in1Plus = false;
|
|
isSuperCard = false;
|
|
isOmega = true;
|
|
// Set_AUTO_save(0);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int checkFlashID() {
|
|
// Check for special carts before using standard checks.
|
|
if (CheckForOmega())return carttype;
|
|
if (CheckForSuperCard())return carttype;
|
|
|
|
// Moved this out of main.c to avoid causing issues with Omega/Non EZ Flash carts.
|
|
CloseNorWrite();
|
|
SetRompage(0);
|
|
SetRampage(16);
|
|
SetShake(0x08);
|
|
|
|
int ewin;
|
|
u32 id;
|
|
|
|
OpenNorWrite();
|
|
id = ReadNorFlashID();
|
|
chip_reset();
|
|
if(id == 0) {
|
|
id = ReadNorFlashID();
|
|
chip_reset();
|
|
}
|
|
CloseNorWrite();
|
|
|
|
carttype = id;
|
|
|
|
switch (id) {
|
|
case 0:
|
|
if (check_M3()) {
|
|
carttype = 6; // M3/G6
|
|
is3in1Plus = false;
|
|
isSuperCard = false;
|
|
isOmega = false;
|
|
return carttype;
|
|
}
|
|
ewin = check_EWIN();
|
|
if(ewin > 0)carttype = (3 + ewin); // EWIN
|
|
is3in1Plus = false;
|
|
isSuperCard = false;
|
|
isOmega = false;
|
|
return carttype;
|
|
case 0x227E2218: carttype = 1; return carttype; // 3in1
|
|
case 0x227E2202: carttype = 2; return carttype; // New3in1
|
|
case 0x89168916: // 3in1 Plus
|
|
is3in1Plus = true;
|
|
isSuperCard = false;
|
|
isOmega = false;
|
|
carttype = 1;
|
|
return carttype;
|
|
case 0x227E2220: carttype = 3; return carttype; // EZ4
|
|
default: return 0; // Unsupported/Unimplemented Cart ID
|
|
}
|
|
}
|
|
|
|
|
|
void _RamPG() {
|
|
if (isSuperCard)return;
|
|
switch (carttype) {
|
|
case 3:
|
|
SetRampage(USE_SRAM_PG_EZ4);
|
|
return;
|
|
case 4:
|
|
SetEWINRam(USE_SRAM_PG_EWN);
|
|
return;
|
|
case 5:
|
|
SetEWINRam(USE_SRAM_PG_EWN128);
|
|
return;
|
|
case 6:
|
|
SetM3Ram(USE_SRAM_PG_M3);
|
|
return;
|
|
}
|
|
if (isOmega) { SetRampage(16); } else { SetRampage(USE_SRAM_PG); }
|
|
return;
|
|
}
|
|
|
|
void _RamSave(int bnk) {
|
|
if (isSuperCard)return;
|
|
switch (carttype) {
|
|
case 3:
|
|
SetRampage(USE_SRAM_PSR_EZ4 + bnk * 16);
|
|
return;
|
|
case 6:
|
|
SetM3Ram(USE_SRAM_PSR_M3 + bnk);
|
|
return;
|
|
}
|
|
|
|
if(carttype >= 4) {
|
|
SetEWINRam(USE_SRAM_PSR_EWN + bnk);
|
|
return;
|
|
}
|
|
|
|
if(GBAmode == 0) {
|
|
if (isOmega) {
|
|
SetRampage(USE_SRAM_PSR_OMEGA + (bnk * 16));
|
|
} else {
|
|
SetRampage(USE_SRAM_PSR + bnk * 16);
|
|
}
|
|
} else {
|
|
if (isOmega) { SetRampage(USE_SRAM_PSR_OMEGA + (bnk * 16)); return; }
|
|
SetRampage(USE_SRAM_NOR + bnk * 16);
|
|
}
|
|
return;
|
|
}
|
|
|
|
bool checkSRAM_cnf() {
|
|
int i;
|
|
|
|
ctrl_get();
|
|
|
|
for(i = 0; ctrl.sign[i] != 0; i++) {
|
|
if(ctrl.sign[i] != Rudolph[i])break;
|
|
}
|
|
|
|
// _RamSave(0);
|
|
if(Rudolph[i] != 0)return false;
|
|
return true;
|
|
}
|
|
|
|
int checkSRAM(char *name) {
|
|
int i, ln;
|
|
|
|
ctrl_get();
|
|
|
|
for(i = 0; ctrl.sign[i] != 0; i++) {
|
|
if(ctrl.sign[i] != Rudolph[i])break;
|
|
}
|
|
|
|
if((carttype < 4) && !isSuperCard && !is3in1Plus && !isOmega)OpenNorWrite();
|
|
|
|
if(Rudolph[i] != 0) {
|
|
strcpy((char *)ctrl.sign, Rudolph);
|
|
ctrl_set();
|
|
if((carttype < 4) && !isSuperCard && !is3in1Plus && !isOmega)CloseNorWrite();
|
|
return false;
|
|
}
|
|
|
|
savesize = ctrl.save_siz[GBAmode];
|
|
// if (isOmega && savesize > 0x10000)savesize = 0x10000;
|
|
if((savesize < 0x2000) || (savesize > USE_SRAM)) {
|
|
savesize = 0x10000;
|
|
ctrl.save_siz[GBAmode] = savesize;
|
|
}
|
|
|
|
strcpy(name, (char *)ctrl.sav_nam[GBAmode]);
|
|
ln = strlen(name) - 3;
|
|
// if((name[ln] != 's' && name[ln] != 'S') || (name[ln+1] != 'a' && name[ln+1] != 'A') || (name[ln+2] != 'v' && name[ln+2] != 'V')) {
|
|
if((name[ln-1] != '.') || (name[ln] != 's' && name[ln] != 'S')) {
|
|
memset(ctrl.sav_nam[GBAmode], 0, 512);
|
|
name[0] = 0;
|
|
savesize = 0x10000;
|
|
ctrl.save_siz[GBAmode] = savesize;
|
|
ctrl_set();
|
|
if((carttype < 4) && !isSuperCard && !is3in1Plus && !isOmega)CloseNorWrite();
|
|
return false;
|
|
}
|
|
|
|
if((carttype < 4) && !isSuperCard && !is3in1Plus && !isOmega)CloseNorWrite();
|
|
return true;
|
|
}
|
|
|
|
void setGBAmode() {
|
|
if(ctrl.mode != (char)GBAmode) {
|
|
ctrl.mode = (char)GBAmode;
|
|
// if(carttype < 4)
|
|
// OpenNorWrite();
|
|
// ctrl_set();
|
|
// if(carttype < 4)
|
|
// CloseNorWrite();
|
|
}
|
|
}
|
|
|
|
void getGBAmode() {
|
|
// ctrl_get();
|
|
GBAmode = ctrl.mode;
|
|
if((GBAmode < 0) || (GBAmode > 2)) {
|
|
GBAmode = 0;
|
|
ctrl.mode = 0;
|
|
}
|
|
}
|
|
|
|
void setcurpath() {
|
|
memset(ctrl.path, 0, 256);
|
|
strcpy((char*)ctrl.path, curpath);
|
|
ctrl_set();
|
|
}
|
|
|
|
void getcurpath() {
|
|
if(ctrl.path[0] != '/') {
|
|
ctrl.path[0] = '/';
|
|
ctrl.path[1] = 0;
|
|
}
|
|
strcpy(curpath, (char *)ctrl.path);
|
|
}
|
|
|
|
extern void err_cnf(int n1, int n2);
|
|
|
|
/*************
|
|
bool getSaveFilename(int sel, char *savename)
|
|
{
|
|
DIR_ITER *dir;
|
|
struct stat st;
|
|
char fname[256];
|
|
char lfnname[512];
|
|
int len, ln;
|
|
bool exist;
|
|
|
|
|
|
len = strlen(fs[sel].filename) - 3;
|
|
exist = false;
|
|
|
|
dir = diropen("/GBA_SAVE");
|
|
while((dir != NULL) && (dirnextl(dir, fname, lfnname, &st) == 0)) {
|
|
if(st.st_mode & S_IFDIR)
|
|
continue;
|
|
|
|
ln = strlen(fname);
|
|
if(ln < 5) continue;
|
|
if((fname[ln - 4] != '.') || (fname[ln - 3] != 'S') || (fname[ln - 2] != 'A') || (fname[ln - 1] != 'V'))
|
|
continue;
|
|
|
|
if(strncmp(fs[sel].filename, lfnname, len) == 0) {
|
|
exist = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(exist) {
|
|
strcpy(savename, lfnname);
|
|
return true;
|
|
}
|
|
|
|
strncpy(savename, fs[sel].filename, len);
|
|
savename[len] = 0;
|
|
strcat(savename, "sav");
|
|
return false;
|
|
|
|
}
|
|
*******************/
|
|
|
|
bool checkBackup() {
|
|
if (GBAmode == 1) { return true; } else if (ctrl.save_flg[GBAmode] == 0xFF) { return false; }
|
|
return true;
|
|
}
|
|
|
|
|
|
void SRAMdump(int cmd) {
|
|
FILE *dmp;
|
|
int i;
|
|
int mx;
|
|
char name[256];
|
|
|
|
mx = 8;
|
|
|
|
switch (carttype) {
|
|
case 1:
|
|
if (isOmega)mx = 2;
|
|
break;
|
|
case 4: mx = 4; break;
|
|
case 5: mx = 2; break;
|
|
case 6:
|
|
mx = 16;
|
|
if (isSuperCard)mx = 1;
|
|
break;
|
|
}
|
|
|
|
sprintf(name, "%s/SRAM.BIN", ini.save_dir);
|
|
|
|
if(cmd == 0) {
|
|
dsp_bar(4, -1);
|
|
dmp = fopen(name, "wb");
|
|
for(i = 0; i < mx; i++) {
|
|
if(carttype == 6 && !isSuperCard) {
|
|
SetM3Ram(i);
|
|
} else if (!isSuperCard) {
|
|
if((carttype >= 4)) {
|
|
SetEWINRam(8 + i);
|
|
} else if (isOmega) {
|
|
SetRampage(USE_SRAM_PSR_OMEGA + (i * 16));
|
|
} else {
|
|
SetRampage(i * 16);
|
|
}
|
|
}
|
|
|
|
ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2);
|
|
|
|
if(dmp != NULL)fwrite(rwbuf, 1, USE_SRAM / 2, dmp);
|
|
|
|
if (i == 0) {
|
|
dsp_bar(4, 0);
|
|
} else {
|
|
switch (mx) {
|
|
case 2:
|
|
if (i == 1) { dsp_bar(4, 50); } else if (i == 2) { dsp_bar(4, 100); }
|
|
break;
|
|
case 4:
|
|
if (i == 1) { dsp_bar(4, 25); } else if (i == 2) { dsp_bar(4, 50); } else if (i == 3) { dsp_bar(4, 75); } else if (i == 4) { dsp_bar(4, 100); }
|
|
break;
|
|
case 8:
|
|
if (i == 2) { dsp_bar(4, 25); } else if (i == 4) { dsp_bar(4, 50); } else if (i == 6) { dsp_bar(4, 75); } else if (i == 8) { dsp_bar(4, 100); }
|
|
break;
|
|
case 16:
|
|
if (i == 4) { dsp_bar(4, 25); } else if (i == 8) { dsp_bar(4, 50); } else if (i == 12) { dsp_bar(6, 75); } else if (i == 16) { dsp_bar(8, 100); }
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
dsp_bar(5, -1);
|
|
dmp = fopen(name, "rb");
|
|
if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)OpenNorWrite();
|
|
|
|
if (isOmega)Omega_Bank_Switching(0);
|
|
|
|
for(i = 0; i < mx; i++) {
|
|
memset(rwbuf, 0, USE_SRAM / 2);
|
|
if(dmp != NULL)
|
|
fread(rwbuf, 1, USE_SRAM / 2, dmp);
|
|
if(carttype == 6) {
|
|
SetM3Ram(i);
|
|
} else {
|
|
if((carttype >= 4) && !isSuperCard) {
|
|
SetEWINRam(8 + i);
|
|
} else if (isOmega) {
|
|
SetRampage(USE_SRAM_PSR_OMEGA + (i * 16));
|
|
} else {
|
|
SetRampage(i * 16);
|
|
}
|
|
}
|
|
|
|
WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2);
|
|
|
|
if (i == 0) {
|
|
dsp_bar(5, 0);
|
|
} else {
|
|
switch (mx) {
|
|
case 2:
|
|
if (i == 1) { dsp_bar(5, 50); } else if (i == 2) { dsp_bar(5, 100); }
|
|
break;
|
|
case 4:
|
|
if (i == 1) { dsp_bar(5, 25); } else if (i == 2) { dsp_bar(5, 50); } else if (i == 3) { dsp_bar(5, 75); } else if (i == 4) { dsp_bar(5, 100); }
|
|
break;
|
|
case 8:
|
|
if (i == 2) { dsp_bar(5, 25); } else if (i == 4) { dsp_bar(5, 50); } else if (i == 6) { dsp_bar(5, 75); } else if (i == 8) { dsp_bar(5, 100); }
|
|
break;
|
|
case 16:
|
|
if (i == 4) { dsp_bar(5, 25); } else if (i == 8) { dsp_bar(5, 50); } else if (i == 12) { dsp_bar(5, 75); } else if (i == 16) { dsp_bar(5, 100); }
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)CloseNorWrite();
|
|
}
|
|
fclose(dmp);
|
|
_RamSave(0);
|
|
dsp_bar(-1, 100);
|
|
}
|
|
|
|
void blankSRAM(char *savename) {
|
|
|
|
memset(rwbuf, 0xFF, USE_SRAM / 2);
|
|
|
|
if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)OpenNorWrite();
|
|
|
|
if (isOmega)Omega_Bank_Switching(0);
|
|
|
|
_RamSave(0);
|
|
|
|
WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2);
|
|
|
|
// if(carttype != 5) {
|
|
if (!isSuperCard && !isOmega) {
|
|
_RamSave(1);
|
|
WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2);
|
|
}
|
|
// }
|
|
|
|
ctrl.save_siz[GBAmode] = savesize;
|
|
ctrl.save_flg[GBAmode] = 0x00;
|
|
memset(ctrl.sav_nam[GBAmode], 0, 512);
|
|
strcpy((char *)ctrl.sav_nam[GBAmode], savename);
|
|
ctrl_set();
|
|
|
|
if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)CloseNorWrite();
|
|
}
|
|
|
|
void writeSramToFile(char *savename) {
|
|
FILE *saver;
|
|
u32 len;
|
|
|
|
if(savename[0] == 0) return;
|
|
|
|
// if((GBAmode == 0) && (checkBackup() == false))return;
|
|
|
|
// getSaveFilename(filename, tbuf);
|
|
sprintf(tbuf, "%s/%s", ini.save_dir, savename);
|
|
saver = fopen(tbuf, "wb");
|
|
// memset(rwbuf, 0, USE_SRAM / 2);
|
|
// OpenNorWrite();
|
|
|
|
_RamSave(0);
|
|
|
|
ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2);
|
|
|
|
if(saver != NULL) {
|
|
len = USE_SRAM / 2;
|
|
if(len > savesize)len = savesize;
|
|
fwrite(rwbuf, 1, len, saver);
|
|
}
|
|
if((savesize > (USE_SRAM / 2)) && !isSuperCard && !isOmega) {
|
|
_RamSave(1);
|
|
ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2);
|
|
if(saver != NULL)fwrite(rwbuf, 1, USE_SRAM / 2, saver);
|
|
}
|
|
fclose(saver);
|
|
|
|
ctrl.save_flg[GBAmode] = 0xFF;
|
|
|
|
if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)OpenNorWrite();
|
|
|
|
ctrl_set();
|
|
|
|
if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)CloseNorWrite();
|
|
}
|
|
|
|
void writeSramFromFile(char *savename) {
|
|
FILE *saver;
|
|
|
|
if(savename[0] == 0) return;
|
|
|
|
sprintf(tbuf, "%s/%s", ini.save_dir, savename);
|
|
// getSaveFilename(filename, tbuf);
|
|
|
|
saver = fopen(tbuf, "rb");
|
|
if(saver == NULL) {
|
|
blankSRAM(savename);
|
|
// writeSramToFile(uniName);
|
|
return;
|
|
}
|
|
|
|
if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)OpenNorWrite();
|
|
|
|
ctrl.save_siz[GBAmode] = savesize;
|
|
ctrl.save_flg[GBAmode] = 0x00;
|
|
memset(ctrl.sav_nam[GBAmode], 0, 512);
|
|
strcpy((char *)ctrl.sav_nam[GBAmode], savename);
|
|
ctrl_set();
|
|
|
|
// OpenNorWrite();
|
|
|
|
if (isOmega)Omega_Bank_Switching(0);
|
|
|
|
_RamSave(0);
|
|
|
|
memset(rwbuf, 0xFF, USE_SRAM / 2);
|
|
fread(rwbuf, 1, USE_SRAM / 2, saver);
|
|
|
|
WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2);
|
|
|
|
// if(carttype != 5) {
|
|
if((savesize > (USE_SRAM / 2)) && !isSuperCard && !isOmega) {
|
|
_RamSave(1);
|
|
memset(rwbuf, 0xFF, USE_SRAM / 2);
|
|
fread(rwbuf, 1, USE_SRAM / 2, saver);
|
|
WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2);
|
|
_RamSave(0);
|
|
}
|
|
// }
|
|
|
|
if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)CloseNorWrite();
|
|
|
|
fclose(saver);
|
|
}
|
|
|
|
|
|
/*void _ReadPSram(uint32 address, u8* data , uint32 size) {
|
|
u32 i;
|
|
u16* pData = (u16*)data;
|
|
u16* sData = (u16*)address;
|
|
|
|
for(i = 0; i < size / 2; i++)pData[i] = sData[i];
|
|
}
|
|
|
|
void _WritePSram(uint32 address, u8* data , uint32 size) {
|
|
u32 i;
|
|
u16* sData = (u16*)data;
|
|
u16* pData = (u16*)address;
|
|
|
|
for(i = 0; i < size / 2; i++)pData[i] = sData[i];
|
|
}*/
|
|
|
|
|
|
int writeFileToNor(int sel) {
|
|
FILE *gbaFile;
|
|
char savName[512];
|
|
u32 siz, wsz;
|
|
u32 exp, ofs;
|
|
u32 fsz;
|
|
int cmd;
|
|
bool gba;
|
|
|
|
if (is3in1Plus) { fsz = MAX_NORPLUS; } else { fsz = MAX_NOR; }
|
|
|
|
exp = 0x00000000;
|
|
|
|
if(fs[sel].filesize > fsz)return 1;
|
|
|
|
if(!checkSRAM(savName)) {
|
|
err_cnf(4, 5);
|
|
} else {
|
|
if(save_sel(1, savName) >= 0)writeSramToFile(savName);
|
|
}
|
|
|
|
if((fs[sel].filename[strlen(fs[sel].filename) - 3] != 'G') || (fs[sel].filename[strlen(fs[sel].filename) - 3] != 'g')) { gba = false; } else { gba = true; }
|
|
|
|
sprintf(tbuf, "%s%s", curpath, fs[sel].filename);
|
|
|
|
gbaFile = fopen(tbuf, "rb");
|
|
if(gbaFile == NULL) return(0);
|
|
|
|
strcpy(savName, fs[sel].filename);
|
|
cmd = save_sel(0, savName);
|
|
|
|
SetRompage(0);
|
|
OpenNorWrite();
|
|
SetSerialMode();
|
|
dsp_bar(0, -1);
|
|
|
|
for(siz = 0; siz < fs[sel].filesize; siz += 0x40000) {
|
|
dsp_bar(0, siz * 100 / fs[sel].filesize);
|
|
if (is3in1Plus) { Block_EraseIntel(siz); } else { Block_Erase(siz); }
|
|
}
|
|
|
|
dsp_bar(0, 100);
|
|
|
|
chip_reset();
|
|
CloseNorWrite();
|
|
|
|
SetRampage(USE_SRAM_NOR);
|
|
OpenNorWrite();
|
|
SetSerialMode();
|
|
|
|
gba_check_int(fs[sel].filename);
|
|
dsp_bar(-1, 100);
|
|
|
|
savesize = gba_check(gbaFile, fs[sel].filesize, rwbuf, PSRAM_BUF*32);
|
|
dsp_bar(1, -1);
|
|
|
|
for(siz = 0; siz < fs[sel].filesize; siz += PSRAM_BUF*32) {
|
|
fread(rwbuf, 1, PSRAM_BUF*32, gbaFile);
|
|
|
|
// dsp_bar(1, siz * 100 / fs[sel].filesize);
|
|
|
|
if(siz == 0 && gba)header_rep(rwbuf);
|
|
|
|
wsz = fs[sel].filesize - siz;
|
|
if(wsz > PSRAM_BUF*32) wsz = PSRAM_BUF*32;
|
|
|
|
gba_patch(rwbuf, siz, wsz, GBAmode, fs[sel].filename);
|
|
|
|
for(ofs = 0; ofs < wsz; ofs += PSRAM_BUF) {
|
|
dsp_bar(1, (siz + ofs) * 100 / fs[sel].filesize);
|
|
WriteNorFlash(exp, rwbuf + ofs, PSRAM_BUF);
|
|
exp += PSRAM_BUF;
|
|
}
|
|
}
|
|
|
|
dsp_bar(1, 100);
|
|
fclose(gbaFile);
|
|
|
|
// if (is3in1Plus)chip_reset();
|
|
|
|
CloseNorWrite();
|
|
|
|
dsp_bar(5, -1);
|
|
// getSaveFilename(sel, savName);
|
|
if(cmd >= 0) { writeSramFromFile(savName); } else { blankSRAM(savName); }
|
|
|
|
dsp_bar(5, 100);
|
|
|
|
for (int i = 0; i < 30; i++)swiWaitForVBlank();
|
|
|
|
dsp_bar(-1, 100);
|
|
// SetRampage(USE_SRAM_NOR);
|
|
return(0);
|
|
}
|
|
|
|
|
|
int writeFileToRam(int sel) {
|
|
|
|
FILE *gbaFile;
|
|
char savName[512];
|
|
u32 siz;
|
|
u32 exp, exps;
|
|
u32 fsz;
|
|
int cmd;
|
|
bool gba;
|
|
// Needed for EZFlash Omega
|
|
u32 PSRamPage = 0;
|
|
|
|
if (carttype >= 3) { fsz = MAX_NOR; } else if (isOmega) { fsz = MAX_NOR; } else { fsz = MAX_PSRAM; }
|
|
|
|
if (carttype >= 4) { exp = FlashBase; } else if (isOmega) { exp = PSRAMBase_S98; } else { exp = 0x08060000; }
|
|
|
|
exps = exp;
|
|
|
|
if(fs[sel].filesize > fsz)return 1;
|
|
|
|
// if(checkSRAM(savName) == false) {
|
|
// err_cnf(4, 5);
|
|
// } else writeSramToFile(savName);
|
|
|
|
if((fs[sel].filename[strlen(fs[sel].filename) - 3] != 'G') || (fs[sel].filename[strlen(fs[sel].filename) - 3] != 'g')) { gba = false; } else { gba = true; }
|
|
|
|
sprintf(tbuf, "%s%s", curpath, fs[sel].filename);
|
|
|
|
gbaFile = fopen(tbuf, "rb");
|
|
if (gbaFile == NULL)return 0;
|
|
|
|
strcpy(savName, fs[sel].filename);
|
|
cmd = save_sel(0, savName);
|
|
|
|
// SetRampage(USE_SRAM_PSR);
|
|
if((carttype < 4) && !isSuperCard && !isOmega) {
|
|
if(carttype == 3) { SetRompage(0x300 - 3); } else { SetRompage(384 - 3); }
|
|
OpenNorWrite();
|
|
} else if (isOmega) {
|
|
SetSDControl(0);
|
|
Set_RTC_status(1);
|
|
SetPSRampage(0);
|
|
// Omega_InitFatBuffer(OMEGA_UNKNOWN, Omega_SetSaveSize(OMEGA_UNKNOWN), fs[sel].filesize);
|
|
}
|
|
|
|
// savesize = gba_check(gbaFile, fs[sel].filesize, rwbuf, 0x100000);
|
|
// if(savesize == 0)savesize = 0x8000;
|
|
|
|
dsp_bar(2, -1);
|
|
|
|
gba_check_int(fs[sel].filename);
|
|
|
|
DC_FlushRange((void*)rwbuf, (0x100000 + 0x400));
|
|
|
|
for(siz = 0; siz < fs[sel].filesize; siz += 0x100000, exp += 0x100000) {
|
|
fseek(gbaFile, siz, SEEK_SET);
|
|
fread(rwbuf, 1, 0x100000+0x400, gbaFile);
|
|
|
|
dsp_bar(2, siz * 100 / fs[sel].filesize);
|
|
|
|
if(siz == 0 && gba)header_rep(rwbuf);
|
|
|
|
savesize = gba_check_Ram1(rwbuf, 0x100000, fs[sel].filesize, siz);
|
|
|
|
// EZ Flash Omega and it's silly mapping schemes.... :P
|
|
if (isOmega) {
|
|
if (exp >= 0x09000000) {
|
|
PSRamPage += 0x1000;
|
|
SetPSRampage(PSRamPage);
|
|
exp = PSRAMBase_S98;
|
|
}
|
|
}
|
|
|
|
dmaCopy((void*)rwbuf, (void*)exp, 0x100000);
|
|
// _WritePSram(exp, rwbuf, 0x100000);
|
|
// dmaCopyWords(3, rwbuf, (void *)exp, 0x100000);
|
|
}
|
|
|
|
DC_FlushRange((void*)rwbuf, 0x100000);
|
|
|
|
if (isOmega) {
|
|
if (savesize > 0x10000)savesize = 0x10000;
|
|
SetPSRampage(0);
|
|
}
|
|
|
|
dsp_bar(2, 100);
|
|
|
|
if (isSuperCard) {
|
|
if (savesize > 0x10000)savesize = 0x10000;
|
|
bool allowPatches = true;
|
|
dsp_bar(-1, 100);
|
|
dsp_bar(3, -1);
|
|
dsp_bar(3, 25);
|
|
patchGeneralWhiteScreen(fs[sel].filesize);
|
|
allowPatches = patchSpecificGame();
|
|
dsp_bar(3, 50);
|
|
romSize = fs[sel].filesize;
|
|
const struct save_type* saveType = allowPatches ? save_findTag() : NULL;
|
|
dsp_bar(3, 75);
|
|
if (saveType != NULL && saveType->patchFunc != NULL)saveType->patchFunc(saveType);
|
|
dsp_bar(3, 100);
|
|
for (int I = 0; I < 50; I++)swiWaitForVBlank();
|
|
dsp_bar(-1, 100);
|
|
} else {
|
|
gba_check_Ram2(exps, rwbuf, 0x100000, fs[sel].filesize);
|
|
dsp_bar(-1, 100);
|
|
}
|
|
|
|
dsp_bar(5, -1);
|
|
|
|
if (!isSuperCard)gba_patch_Ram(exps, fs[sel].filename, carttype);
|
|
|
|
fclose(gbaFile);
|
|
|
|
// if(carttype == 5 && savesize == 0x20000) {
|
|
// dsp_bar(-1, 100);
|
|
// return(2);
|
|
// }
|
|
|
|
// getSaveFilename(sel, savName);
|
|
dsp_bar(5, 50);
|
|
|
|
if(cmd >= 0) { writeSramFromFile(savName); } else { blankSRAM(savName); }
|
|
|
|
if((carttype < 4) && !isSuperCard && !isOmega)CloseNorWrite();
|
|
|
|
_RamSave(0);
|
|
|
|
if(carttype >= 4 && !isSuperCard) {
|
|
if(carttype == 6) { Close_M3(); } else { Close_EWIN(); }
|
|
}
|
|
|
|
dsp_bar(5, 100);
|
|
|
|
for (int i = 0; i < 30; i++)swiWaitForVBlank();
|
|
|
|
dsp_bar(-1, 100);
|
|
|
|
if (isSuperCard)return 0;
|
|
|
|
if (isOmega) {
|
|
rtc_toggle(true);
|
|
SetRompage(0x200);
|
|
return 0;
|
|
}
|
|
|
|
if (carttype == 3) { SetRompage(0x300); } else if (carttype <= 2) { SetRompage(384); }
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void QSort(int left, int right) {
|
|
int i, j;
|
|
int p;
|
|
int tmp;
|
|
|
|
i = left;
|
|
j = right;
|
|
|
|
p = sortfile[(i + j) / 2];
|
|
|
|
|
|
while(1) {
|
|
while(strcmp((char *)&(fs[sortfile[i]].type), (char *)&(fs[p].type)) < 0)
|
|
i++;
|
|
while(strcmp((char *)&(fs[sortfile[j]].type), (char *)&(fs[p].type)) > 0)
|
|
j--;
|
|
// while(strcmp(fs[sortfile[i]].filename, fs[p].filename) < 0)
|
|
// i++;
|
|
// while(strcmp(fs[sortfile[j]].filename, fs[p].filename) > 0)
|
|
// j--;
|
|
if(i >= j) break;
|
|
|
|
tmp = sortfile[i];
|
|
sortfile[i] = sortfile[j];
|
|
sortfile[j] = tmp;
|
|
i++;
|
|
j--;
|
|
}
|
|
|
|
if(left < i - 1)
|
|
QSort(left, i - 1);
|
|
if(right > j + 1)
|
|
QSort(j + 1, right);
|
|
}
|
|
|
|
|
|
static void _sort_file() {
|
|
int i, j;
|
|
int no;
|
|
|
|
// for(i = 0; i < numFiles; i++)
|
|
// sortfile[i] = i;
|
|
|
|
for(i = 0; i < numFiles; i++ ) {
|
|
for (j = 1; j < numFiles; j++) {
|
|
if((fs[sortfile[j]].type & S_IFMT) && (fs[sortfile[j]].type & S_IFDIR)) {
|
|
no = sortfile[j - 1];
|
|
sortfile[j - 1] = sortfile[j];
|
|
sortfile[j] = no;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < numFiles; i++) {
|
|
for (j = 0; j < numFiles - 1; j++) {
|
|
if(fs[sortfile[j]].type != fs[sortfile[j + 1]].type)
|
|
continue;
|
|
if(strcmp(fs[sortfile[j]].filename, "..") == 0)
|
|
continue;
|
|
if(strcmp(fs[sortfile[j]].filename, fs[sortfile[j + 1]].filename) > 0 ) {
|
|
no = sortfile[j + 1];
|
|
sortfile[j + 1] = sortfile[j];
|
|
sortfile[j] = no;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool nameEndsWith (const string& name, const string& extension) {
|
|
if (name.size() == 0) return false;
|
|
if (name.front() == '.') return false;
|
|
|
|
const string ext = extension;
|
|
if (strcasecmp(name.c_str() + name.size() - ext.size(), ext.c_str()) == 0)return true;
|
|
return false;
|
|
}
|
|
|
|
void FileListGBA() {
|
|
DIR *dir;
|
|
struct stat st;
|
|
FILE *gbaFile;
|
|
int i;
|
|
const char* GBAEXT = ".GBA";
|
|
const char* BINEXT = ".BIN";
|
|
|
|
numFiles = 0;
|
|
numGames = 0;
|
|
|
|
chdir (curpath);
|
|
dir = opendir(curpath);
|
|
|
|
// if(dir == NULL) {
|
|
if(!dir) {
|
|
strcpy(curpath, "/");
|
|
dir = opendir(curpath);
|
|
}
|
|
|
|
|
|
// if (dir != NULL) {
|
|
if (dir) {
|
|
while(1) {
|
|
dirent* pent = readdir(dir);
|
|
// if(pent == NULL)break;
|
|
if(!pent)break;
|
|
stat(pent->d_name, &st);
|
|
if ((((st.st_mode & S_IFMT) == S_IFDIR) && (((string)pent->d_name).compare(".") != 0)) || nameEndsWith(pent->d_name, GBAEXT) || nameEndsWith(pent->d_name, BINEXT)) {
|
|
strcpy(fs[numFiles].filename, pent->d_name);
|
|
// strcpy(fs[numFiles].Alias, pent->d_name);
|
|
fs[numFiles].type = st.st_mode;
|
|
if ((((string)pent->d_name).compare(".") != 0) && (((string)pent->d_name).compare("..") != 0) && ((st.st_mode & S_IFMT) != S_IFDIR)) {
|
|
FILE *file = fopen(pent->d_name, "rb");
|
|
if (file) {
|
|
fseek(file, 0, SEEK_END);
|
|
fs[numFiles].filesize = ftell(file);
|
|
fclose(file);
|
|
}
|
|
}
|
|
numFiles++;
|
|
if (numFiles > 199)break;
|
|
}
|
|
}
|
|
closedir(dir);
|
|
|
|
for(i = 0; i < numFiles; i++) {
|
|
sortfile[i] = i;
|
|
if(fs[i].type & S_IFDIR) {
|
|
fs[i].gamecode[0] = 0;
|
|
fs[i].gametitle[0] = 0;
|
|
} else {
|
|
sprintf(tbuf, "%s%s", curpath, fs[i].filename);
|
|
if (access(tbuf, F_OK) == 0) {
|
|
gbaFile = fopen(tbuf, "rb");
|
|
memset(tbuf, 0, 256);
|
|
if(gbaFile != NULL) {
|
|
fread(tbuf, 1, 256, gbaFile);
|
|
tbuf[0xB0] = 0;
|
|
strcpy(fs[i].gamecode, tbuf + 0xAC);
|
|
tbuf[0xAC] = 0;
|
|
strcpy(fs[i].gametitle, tbuf + 0xA0);
|
|
fclose(gbaFile);
|
|
} else {
|
|
fs[i].gamecode[0] = 0;
|
|
fs[i].gametitle[0] = 0;
|
|
}
|
|
} else {
|
|
fs[i].gamecode[0] = 0;
|
|
fs[i].gametitle[0] = 0;
|
|
}
|
|
numGames++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(numFiles > 1)_sort_file();
|
|
}
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|