Commits

Anonymous committed 3e3b185

*Changed the configGetString function to return a const value, since the configuration keys are not to be changed without configSetStr(), except for two lines within themes.c. This is to safeguard against accidental configuration corruption/overwriting.
*Added a slightly modified version of the OSD game history updating system from FMCB, although it's disabled because it still isn't working right.

For some reason, the added history records (BRDATA-SYSTEM/history, where R is your console's folder region letter) have no filename and appear to be duplicated across the entire file.

  • Participants
  • Parent commits 133e4e2

Comments (0)

Files changed (24)

 #change following line to "0" to build without GSM - DO NOT COMMENT!
 GSM = 0
 
-FRONTEND_OBJS = obj/pad.o obj/fntsys.o obj/renderman.o obj/menusys.o obj/system.o obj/debug.o obj/lang.o obj/config.o obj/hdd.o obj/dialogs.o \
+FRONTEND_OBJS = obj/pad.o obj/fntsys.o obj/renderman.o obj/menusys.o obj/OSDHistory.o obj/system.o obj/debug.o obj/lang.o obj/config.o obj/hdd.o obj/dialogs.o \
 		obj/dia.o obj/ioman.o obj/texcache.o obj/themes.o obj/supportbase.o obj/usbsupport.o obj/ethsupport.o obj/hddsupport.o \
 		obj/appsupport.o obj/gui.o obj/textures.o obj/opl.o obj/atlas.o
 
 		obj/load0.o obj/load1.o obj/load2.o obj/load3.o obj/load4.o obj/load5.o obj/load6.o obj/load7.o obj/logo.o obj/freesans.o \
 		obj/icon_sys.o obj/icon_icn.o
 
+MISC_OBJS =	obj/icon_sys_A.o obj/icon_sys_J.o
+
 EECORE_OBJS = obj/ee_core.o \
 		obj/alt_ee_core.o obj/elfldr.o obj/imgdrv.o obj/eesync.o \
 		obj/usb_cdvdman.o obj/usb_4Ksectors_cdvdman.o obj/smb_cdvdman.o obj/smb_pcmcia_cdvdman.o \
 EE_SRC_DIR = src/
 EE_OBJS_DIR = obj/
 EE_ASM_DIR = asm/
-EE_OBJS = $(FRONTEND_OBJS) $(GFX_OBJS) $(EECORE_OBJS)
+EE_OBJS = $(FRONTEND_OBJS) $(GFX_OBJS) $(MISC_OBJS) $(EECORE_OBJS)
 MAPFILE = opl.map
 
 EE_LIBS = -L$(PS2SDK)/ports/lib -L$(GSKIT)/lib -lgskit -ldmakit -lgskit_toolkit -lpoweroff -lfileXio -lpatches -lpad -ljpeg -lpng -lz -ldebug -lm -lmc -lfreetype -lvux -lcdvd
 	
 icon_icn.s:
 	bin2s gfx/opl.icn asm/icon_icn.s icon_icn	
-  
+
+icon_sys_A.s:
+	bin2s misc/icon_A.sys asm/icon_sys_A.s icon_sys_A
+
+icon_sys_J.s:
+	bin2s misc/icon_J.sys asm/icon_sys_J.s icon_sys_J
+
 $(EE_OBJS_DIR)%.o : $(EE_SRC_DIR)%.c
 	$(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c $< -o $@
 

include/OSDHistory.h

+#define MAX_HISTORY_ENTRIES	21
+
+/*
+	If the record is valid, the launch count will be >0.
+
+	Starts with:
+		SLPM_550.52, data: 01 01 00 00 75 1a
+	After 2 launches:
+		SLPM_550.52, data: 02 01 00 00 75 1a
+	After 15 launches:
+		SLPM_550.52, data: 0e 11 04 00 75 1a
+	Clock advanced 1 day:
+		SLPM_550.52, data: 01 01 00 00 76 1a
+	Clock advanced 1 year:
+		SLPM_550.52, data: 01 01 00 00 75 1c
+	Clock set to Jan 1 2013:
+		SLPM_550.52, data: 01 01 00 00 21 1a
+
+	//0x002187e8	- Not sure what this is. rand?
+	static unsigned int var_0028b020=1;	//0x0028b020
+	static int func_002187e8(void){
+		var_0028b020=(var_0028b020*0x41c64e6d+0x3039);
+		return(var_0028b020&0x7FFFFFFF);
+	}
+
+	//0x002021a0, OSDSYS 1.00, ROM 1.01
+	int value, LeastUsedRecord, LeastUsedRecordLaunchCount, LeastUsedRecordTimestamp;
+
+	for(i=0,LeastUsedRecord=0,LeastUsedRecordTimestamp=LeastUsedRecordLaunchCount=0x7FFFFFFF; i<21; i++){
+		if(entry.LaunchCount<LeastUsedRecordLaunchCount){
+			LeastUsedRecord=i;
+			LeastUsedRecordLaunchCount=entry.LaunchCount;
+		}
+		if(LeastUsedRecord==i){
+			if(entry.timestamp<LeastUsedRecordTimestamp){
+				LeastUsedRecordTimestamp=entry.timestamp;
+				LeastUsedRecord=i;
+			}
+		}
+
+		//0x0020220c
+		if(!strcmp(entry.filename, filename)){
+			if(entry.data[1]&0x3F!=0x3F){
+				entry.LaunchCount++;
+				if(entry.LaunchCount>=0x80){
+					entry.LaunchCount=0x7F;
+				}
+
+				if(entry.LaunchCount>=0xE){
+					if((entry.LaunchCount-14)%10){
+						while((entry.data[1]>>(value=func_002187e8()%6)&1){};
+						entry.data[2]=value;
+						entry.data[1]|=1<<value;
+					}
+				}
+			}
+			else{
+				//0x0020237c
+				if(entry.LaunchCount<0x40){
+					entry.LaunchCount++;
+				}
+				else{
+					entry.LaunchCount=entry.data[1]&0x3F;
+					entry.data[2]=7;
+				}
+			}
+		}
+	}
+
+	//0x002023bc
+	//The code here counts the number of blank slot, and uses the least used slot. If the least used slot is not empty, the original content is copied out (To be appended to history.old).
+	//If there are blank slots, it does this to determine which slot to use:
+		BlankSlotList[func_002187e8()%BlankSlots]
+
+	Conclusion:
+		data[0] = LaunchCount
+		data[1] = ?? (A bitmask)
+		data[2] = ?? (The last shift amount used for generating the value of data[1])
+		data[3] = ?? (Seems to not be initialized)
+		data[4-5] = Timestamp in format: YYYYYYYMMMMDDDDD
+		Note: Year is since year 2000.
+*/
+
+#define OSD_HISTORY_GET_YEAR(datestamp) ((datestamp)>>9&0x7F)
+#define OSD_HISTORY_GET_MONTH(datestamp) ((datestamp)>>5&0xF)
+#define OSD_HISTORY_GET_DATE(datestamp) ((datestamp)&0x1F)
+#define OSD_HISTORY_SET_DATE(year, month, date) (((unsigned short int)(year))<<9 | ((unsigned short int)(month)&0xF)<<5 | ((date)&0x1F))
+
+struct HistoryEntry{
+	char name[16];
+	unsigned char LaunchCount;
+	unsigned char bitmask;
+	unsigned char ShiftAmount;
+	unsigned char padding;
+	unsigned short int DateStamp;
+};
+
+//Functions
+int LoadHistoryFile(const char *path, struct HistoryEntry *HistoryEntries);
+int SaveHistoryFile(const char *path, const struct HistoryEntry *HistoryEntries);
+int AddOldHistoryFileRecord(const char *path, const struct HistoryEntry *OldHistoryEntry);
+int AddHistoryRecord(const char *name);
+int AddHistoryRecordUsingFullPath(const char *path);
+
 void configFree(config_set_t *configSet);
 config_set_t *configGetByType(int type);
 int configSetStr(config_set_t* configSet, const char* key, const char* value);
-int configGetStr(config_set_t* configSet, const char* key, char** value);
+int configGetStr(config_set_t* configSet, const char* key, const char** value);
 void configGetStrCopy(config_set_t* configSet, const char* key, char* value);
 int configSetInt(config_set_t* configSet, const char* key, const int value);
 int configGetInt(config_set_t* configSet, const char* key, int* value);
 	char* name;
 } language_t;
 
-void lngInit();
-char* lngGetValue();
-void lngEnd();
+void lngInit(void);
+char* lngGetValue(void);
+void lngEnd(void);
 
 // Indices are shifted in GUI, as we add the internal english language at 0
 void lngSetGuiValue(int langGuiId);
-int lngGetGuiValue();
-int lngFindGuiID(char* lang);
-char **lngGetGuiList();
+int lngGetGuiValue(void);
+int lngFindGuiID(const char* lang);
+char **lngGetGuiList(void);
 
 #endif

include/texcache.h

 
 /** Initializes a single cache 
 */
-image_cache_t* cacheInitCache(int userId, char* prefix, int isPrefixRelative, char* suffix, int count);
+image_cache_t* cacheInitCache(int userId, const char* prefix, int isPrefixRelative, const char* suffix, int count);
 
 /** Destroys a given cache (unallocates all memory stored there, disconnects the pixmaps from the usage points).
 */

include/textures.h

 #define ERR_MISSING_ALPHA -6
 #define ERR_BAD_DEPTH     -7
 
-int texPngLoad(GSTEXTURE *texture, char *path, int texId, short psm);
-int texJpgLoad(GSTEXTURE* texture, char* path, int texId, short psm);
+int texPngLoad(GSTEXTURE *texture, const char *path, int texId, short psm);
+int texJpgLoad(GSTEXTURE* texture, const char* path, int texId, short psm);
 void texPrepare(GSTEXTURE* texture, short psm);
-int texDiscoverLoad(GSTEXTURE* texture, char* path, int texId, short psm);
+int texDiscoverLoad(GSTEXTURE* texture, const char* path, int texId, short psm);
 
 #endif
 typedef struct {
 	int displayedItems;
 
-	char* decorator;
+	const char* decorator;
 	mutable_image_t* decoratorImage;
 } items_list_t;
 
 
 theme_t* gTheme;
 
-void thmInit();
-void thmReinit(char* path);
-void thmReloadScreenExtents();
-void thmAddElements(char* path, char* separator, int mode);
-char* thmGetValue();
+void thmInit(void);
+void thmReinit(const char* path);
+void thmReloadScreenExtents(void);
+void thmAddElements(char* path, const char* separator, int mode);
+const char* thmGetValue(void);
 GSTEXTURE* thmGetTexture(unsigned int id);
-void thmEnd();
+void thmEnd(void);
 
 // Indices are shifted in GUI, as we add the internal default theme at 0
 int thmSetGuiValue(int themeGuiId, int reload);
-int thmGetGuiValue();
-int thmFindGuiID(char* theme);
-char **thmGetGuiList();
+int thmGetGuiValue(void);
+int thmFindGuiID(const char* theme);
+const char **thmGetGuiList(void);
 
 #endif
 
 // ------------------------------------------------------------------------------------------------------------------------
 
+/// DTV 576 Progressive Scan (720x576)
+#define GS_MODE_DTV_576P  0x53
+
+/// DTV 1080 Progressive Scan (1920x1080)
+#define GS_MODE_DTV_1080P  0x54
+
+#ifdef GSM
 #define GSM_VERSION "0.36.R"
 
 #define PS1_VMODE	1
 	(((u64)(dh)<<44) | ((u64)(dw)<<32) | ((u64)(magv)<<27) | \
 	((u64)(magh)<<23) | ((u64)(dy)<<12)   | ((u64)(dx)<<0)     )
 
-/// DTV 576 Progressive Scan (720x576)
-#define GS_MODE_DTV_576P  0x53
-
-/// DTV 1080 Progressive Scan (1920x1080)
-#define GS_MODE_DTV_1080P  0x54
-
 typedef struct predef_vmode_struct {
 	u8	category;
 	char desc[34];
 int	gGSMXOffset; // 0 - Off, Any other positive or negative value - Relative position for X Offset
 int	gGSMYOffset; // 0 - Off, Any other positive or negative value - Relative position for Y Offset
 int	gGSMSkipVideos; // 0 - Off, 1 - On
+#endif
 
 // ------------------------------------------------------------------------------------------------------------------------
 
 
 int gRememberLastPlayed;
 
+#ifdef GSM
 int gShowGSM; // Toggle to reveal "GSM Settings" on Main Menu
+#endif
 
 char *infotxt;
 
 int openFile(char* path, int mode);
 void* readFile(char* path, int align, int* size);
 void checkCreateDir(char* path);
-int listDir(char* path, char* separator, int maxElem,
-		int (*readEntry)(int index, char *path, char* separator, char* name, unsigned int mode));
+int listDir(char* path, const char* separator, int maxElem,
+		int (*readEntry)(int index, const char *path, const char* separator, const char* name, unsigned int mode));
 
 typedef struct {
 	int fd;
 int fromHex(char digit);
 char toHex(int digit);
 
+int InitConsoleRegionData(void);
+const char *GetSystemDataPath(void);
+char GetSystemFolderLetter(void);
+
 #endif

misc/icon_A.sys

Binary file added.

misc/icon_J.sys

Binary file added.
+#include <errno.h>
+#include <kernel.h>
+#include <libcdvd.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "include/util.h"
+#include "include/OSDHistory.h"
+
+#define SONY_SYSDATA_ICON_SYS_SIZE	1776	//The OSDs have this weird bug (or a feature, whichever one you prefer) whereby the size of the icon file is hardcoded to 1776 bytes... even though that is way too long! Unfortunately, using the right size will cause the icon to be deemed as corrupted data by the HDDOSD. :/
+
+extern unsigned char icon_sys_A[];
+extern unsigned char icon_sys_J[];
+
+#define DEBUG_PRINTF(args...)
+
+int CreateSystemDataFolder(const char *path, char FolderRegionLetter){
+	char fullpath[64];
+	int fd, result, size;
+	void *icon;
+
+	sprintf(fullpath, "%s/icon.sys", path);
+	if((fd=open(fullpath, O_RDONLY))<0){
+		mkdir(path);
+		if((fd=open(fullpath, O_CREAT|O_TRUNC|O_WRONLY))>=0){
+			if(FolderRegionLetter=='I'){
+				icon=icon_sys_J;
+				size=SONY_SYSDATA_ICON_SYS_SIZE;
+			}
+			else{
+				icon=icon_sys_A;
+				size=SONY_SYSDATA_ICON_SYS_SIZE;
+			}
+			result=write(fd, icon, size)==size?0:-EIO;	//Yes, just let it write past the end of the icon. Read the comment above.
+			close(fd);
+		}
+		else result=fd;
+	}
+	else{
+		close(fd);
+		result=0;
+	}
+
+	return result;
+}
+
+int LoadHistoryFile(const char *path, struct HistoryEntry *HistoryEntries){
+	char fullpath[64];
+	int fd, result;
+
+	sprintf(fullpath, "%s/history", path);
+	if((fd=open(fullpath, O_RDONLY))>=0){
+		result=read(fd, HistoryEntries, MAX_HISTORY_ENTRIES*sizeof(struct HistoryEntry))==(MAX_HISTORY_ENTRIES*sizeof(struct HistoryEntry))?0:-EIO;
+		close(fd);
+	}
+	else result=fd;
+
+	return result;
+}
+
+int SaveHistoryFile(const char *path, const struct HistoryEntry *HistoryEntries){
+	char fullpath[64];
+	int fd, result;
+
+	sprintf(fullpath, "%s/history", path);
+	if((fd=open(fullpath, O_WRONLY|O_CREAT|O_TRUNC))>=0){
+		result=write(fd, HistoryEntries, MAX_HISTORY_ENTRIES*sizeof(struct HistoryEntry))==(MAX_HISTORY_ENTRIES*sizeof(struct HistoryEntry))?0:-EIO;
+		close(fd);
+	}
+	else result=fd;
+
+	return result;
+}
+
+int AddOldHistoryFileRecord(const char *path, const struct HistoryEntry *OldHistoryEntry){
+	char fullpath[64];
+	int fd, result;
+
+	sprintf(fullpath, "%s/history.old", path);
+	if((fd=open(fullpath, O_WRONLY|O_APPEND))>=0){
+		lseek(fd, 0, SEEK_END);
+		result=write(fd, OldHistoryEntry, sizeof(struct HistoryEntry))==sizeof(struct HistoryEntry)?0:-EIO;
+		close(fd);
+	}
+	else result=fd;
+
+	return result;
+}
+
+int AddHistoryRecord(const char *name){
+	struct HistoryEntry HistoryEntries[MAX_HISTORY_ENTRIES], *NewEntry, OldHistoryEntry;
+	int i, value, LeastUsedRecord, LeastUsedRecordLaunchCount, LeastUsedRecordTimestamp, result;
+	unsigned char BlankSlotList[MAX_HISTORY_ENTRIES], NumBlankSlots, IsNewRecord;
+	CdvdClock_t time;
+	char SystemRegionLetter;
+	char path[32];
+
+	DEBUG_PRINTF("Adding history record: %s\n", name);
+
+	sprintf(path, "mc0:/%s", GetSystemDataPath());
+	if((result=LoadHistoryFile(path, HistoryEntries))!=0){
+		path[2]='1';
+		if((result=LoadHistoryFile(path, HistoryEntries))!=0){
+			DEBUG_PRINTF("Error: can't load history file.\n");
+
+			SystemRegionLetter=GetSystemFolderLetter();
+
+			path[2]='0';
+			if((result=CreateSystemDataFolder(path, SystemRegionLetter))!=0){
+				path[2]='1';
+				if((result=CreateSystemDataFolder(path, SystemRegionLetter))!=0){
+					DEBUG_PRINTF("Error: Can't create system data folder: %d\n", result);
+					return result;
+				}
+			}
+
+			memset(HistoryEntries, 0, sizeof(HistoryEntries));
+		}
+	}
+
+	for(i=0,LeastUsedRecord=0,LeastUsedRecordTimestamp=LeastUsedRecordLaunchCount=INT_MAX,IsNewRecord=1; i<MAX_HISTORY_ENTRIES; i++){
+		if(HistoryEntries[i].LaunchCount<LeastUsedRecordLaunchCount){
+			LeastUsedRecord=i;
+			LeastUsedRecordLaunchCount=HistoryEntries[i].LaunchCount;
+		}
+		if(LeastUsedRecord==i){
+			if(HistoryEntries[i].DateStamp<LeastUsedRecordTimestamp){
+				LeastUsedRecordTimestamp=HistoryEntries[i].DateStamp;
+				LeastUsedRecord=i;
+			}
+		}
+
+		if(!strcmp(HistoryEntries[i].name, name)){
+			IsNewRecord=0;
+
+			if((HistoryEntries[i].bitmask&0x3F)!=0x3F){
+				HistoryEntries[i].LaunchCount++;
+				if(HistoryEntries[i].LaunchCount>=0x80){
+					HistoryEntries[i].LaunchCount=0x7F;
+				}
+
+				if(HistoryEntries[i].LaunchCount>=14){
+					if((HistoryEntries[i].LaunchCount-14)%10){
+						while((HistoryEntries[i].bitmask>>(value=rand()%6))&1){};
+						HistoryEntries[i].ShiftAmount=value;
+						HistoryEntries[i].bitmask|=1<<value;
+					}
+				}
+			}
+			else{
+				if(HistoryEntries[i].LaunchCount<0x40){
+					HistoryEntries[i].LaunchCount++;
+				}
+				else{
+					HistoryEntries[i].LaunchCount=HistoryEntries[i].bitmask&0x3F;
+					HistoryEntries[i].ShiftAmount=7;
+				}
+			}
+		}
+	}
+
+	if(IsNewRecord){
+		//Count and consolidate a list of blank slots.
+		for(i=0,NumBlankSlots=0; i<MAX_HISTORY_ENTRIES; i++){
+			if(HistoryEntries[i].LaunchCount==0){
+				BlankSlotList[NumBlankSlots]=i;
+				NumBlankSlots++;
+			}
+		}
+
+		if(NumBlankSlots>0){
+			NewEntry=&HistoryEntries[result=BlankSlotList[rand()%NumBlankSlots]];
+		}
+		else{
+			NewEntry=&HistoryEntries[LeastUsedRecord];
+			memcpy(&OldHistoryEntry, NewEntry, sizeof(OldHistoryEntry));
+
+			AddOldHistoryFileRecord(path, &OldHistoryEntry);
+		}
+
+		//Initialize the new entry.
+		strncpy(NewEntry->name, name, sizeof(NewEntry->name));
+		NewEntry->LaunchCount=1;
+		NewEntry->bitmask=1;
+		NewEntry->ShiftAmount=0;
+		cdReadClock(&time);
+		NewEntry->DateStamp=OSD_HISTORY_SET_DATE(btoi(time.year), btoi(time.month), btoi(time.day));
+	}
+
+	return SaveHistoryFile(path, HistoryEntries);
+}
+
+static void GetBootFilename(const char *bootpath, char *filename){	//Does OPL have a function that strips out the filename from the full path to the file on the CD/DVD?
+	int i, length;
+
+	filename[0]='\0';
+	for(i=length=strlen(bootpath); i>0; i--){
+		if(bootpath[i]=='\\' || bootpath[i]==':' || bootpath[i]=='/'){
+			if(length>2 && bootpath[length-1]=='1' && bootpath[length-2]==';') length-=2;
+			length-=(i+1);
+			strncpy(filename, &bootpath[i+1], length);
+			filename[length]='\0';
+			break;
+		}
+	}
+}
+
+int AddHistoryRecordUsingFullPath(const char *path){
+	char filename[256];
+
+	GetBootFilename(path, filename);
+	return AddHistoryRecord(filename);
+}
+
 }
 
 // sets the value to point to the value str in the config. Do not overwrite - it will overwrite the string in config
-int configGetStr(config_set_t* configSet, const char* key, char** value) {
+int configGetStr(config_set_t* configSet, const char* key, const char** value) {
 	if (!configKeyValidate(key))
 		return 0;
 	
 }
 
 void configGetStrCopy(config_set_t* configSet, const char* key, char* value) {
-	char *valref = NULL;
+	const char *valref = NULL;
 	if (configGetStr(configSet, key, &valref))
 		strncpy(value, valref, 32);
 	else
 }
 
 int configGetInt(config_set_t* configSet, const char* key, int* value) {
-	char *valref = NULL;
+	const char *valref = NULL;
 	if (configGetStr(configSet, key, &valref)) {
 		*value = atoi(valref);
 		return 1;
 }
 
 int configGetColor(config_set_t* configSet, const char* key, unsigned char* color) {
-	char *valref = NULL;
+	const char *valref = NULL;
 	if (configGetStr(configSet, key, &valref)) {
 		strToColor(valref, color);
 		return 1;
 void configGetDiscIDBinary(config_set_t* configSet, void* dst) {
 	memset(dst, 0, 5);
 
-	char *gid = NULL;
+	const char *gid = NULL;
 	if (configGetStr(configSet, CONFIG_ITEM_DNAS, &gid)) {
 		// convert from hex to binary
 		char* cdst = dst;
 
 #ifdef VMC
 void configGetVMC(config_set_t* configSet, char* vmc, int slot) {
-	char *valref = NULL;
+	const char *valref = NULL;
 	char gkey[255];
 	snprintf(gkey, 255, "%s_%d", CONFIG_ITEM_VMC, slot);
 	if (configGetStr(configSet, gkey, &valref))
 	// disconnect from the active SMB session
 	ethSMBDisconnect();
 
-	char *altStartup = NULL;
+	const char *altStartup = NULL;
 	if (configGetStr(configSet, CONFIG_ITEM_ALTSTARTUP, &altStartup))
 		strncpy(filename, altStartup, 32);
 	else
 	diaSetString(diaConfig, CFG_USBPREFIX, gUSBPrefix);
 	diaSetString(diaConfig, CFG_ETHPREFIX, gETHPrefix);
 	diaSetInt(diaConfig, CFG_LASTPLAYED, gRememberLastPlayed);
+#ifdef GSM
 	diaSetInt(diaConfig, CFG_SHOWGSM, gShowGSM);
+#endif
 	diaSetInt(diaConfig, CFG_DEFDEVICE, gDefaultDevice);
 	diaSetInt(diaConfig, CFG_USBMODE, gUSBStartMode);
 	diaSetInt(diaConfig, CFG_HDDMODE, gHDDStartMode);
 		diaGetString(diaConfig, CFG_USBPREFIX, gUSBPrefix);
 		diaGetString(diaConfig, CFG_ETHPREFIX, gETHPrefix);
 		diaGetInt(diaConfig, CFG_LASTPLAYED, &gRememberLastPlayed);
+#ifdef GSM
 		diaGetInt(diaConfig, CFG_SHOWGSM, &gShowGSM);
+#endif
 		diaGetInt(diaConfig, CFG_DEFDEVICE, &gDefaultDevice);
 		diaGetInt(diaConfig, CFG_USBMODE, &gUSBStartMode);
 		diaGetInt(diaConfig, CFG_HDDMODE, &gHDDStartMode);
 	// game id
 	memcpy((void*)((u32)irx + i), &gid, 5);
 
-	char *altStartup = NULL;
+	const char *altStartup = NULL;
 	if (configGetStr(configSet, CONFIG_ITEM_ALTSTARTUP, &altStartup))
 		strncpy(filename, altStartup, 32);
 	else
 	return lang_strs[id];
 }
 
-static void lngFreeFromFile() {
+static void lngFreeFromFile(void) {
 	if (guiLangID == 0)
 		return;
 
 	return 0;
 }
 
-char* lngGetValue() {
+char* lngGetValue(void) {
 	return guiLangNames[guiLangID];
 }
 
-static int lngReadEntry(int index, char* path, char* separator, char* name, unsigned int mode) {
+static int lngReadEntry(int index, const char* path, const char* separator, const char* name, unsigned int mode) {
 	if (!FIO_SO_ISDIR(mode)) {
 		if(strstr(name, ".lng") || strstr(name, ".LNG")) {
 
 	return index;
 }
 
-void lngInit() {
+void lngInit(void) {
 	fntInit();
 
 	nLanguages = listDir(gBaseMCDir, "/", MAX_LANGUAGE_FILES, &lngReadEntry);
 	guiLangNames[nLanguages + 1] = NULL;
 }
 
-void lngEnd() {
+void lngEnd(void) {
 	lngFreeFromFile();
 
 	int i = 0;
 	}
 }
 
-int lngGetGuiValue() {
+int lngGetGuiValue(void) {
 	return guiLangID;
 }
 
-int lngFindGuiID(char* lang) {
+int lngFindGuiID(const char* lang) {
 	if (lang) {
 		int i = 0;
 		for (; i < nLanguages; i++) {
 	return 0;
 }
 
-char **lngGetGuiList() {
+char **lngGetGuiList(void) {
 	return guiLangNames;
 }
 #include "include/system.h"
 #include "include/debug.h"
 #include "include/config.h"
+#include "include/util.h"
 
 #include "include/usbsupport.h"
 #include "include/ethsupport.h"
 	// unlock, the rest is deferred
 	guiUnlock();
 
-	char* temp = NULL;
+	const char* temp = NULL;
 	if (gRememberLastPlayed)
 		configGetStr(configGetByType(CONFIG_LAST), "last_played", &temp);
 
 
 		if (result & CONFIG_OPL) {
 			config_set_t *configOPL = configGetByType(CONFIG_OPL);
-			char *temp;
+			const char *temp;
 
 			configGetInt(configOPL, "scrolling", &gScrollSpeed);
 			configGetColor(configOPL, "bg_color", gDefaultBgColor);
 			configGetInt(configOPL, "vsync", &gVSync);
 			configGetInt(configOPL, "vmode", &gVMode);
 
+#ifdef GSM
 			configGetInt(configOPL, "enable_gsm", &gEnableGSM);
 			configGetInt(configOPL, "gsmvmode", &gGSMVMode);
 			configGetInt(configOPL, "gsm_x_offset", &gGSMXOffset);
 			configGetInt(configOPL, "gsm_y_offset", &gGSMYOffset);
 			configGetInt(configOPL, "gsmskipvideos", &gGSMSkipVideos);
+#endif
 
 			if (configGetStr(configOPL, "theme", &temp))
 				themeID = thmFindGuiID(temp);
 			if (configGetStr(configOPL, "eth_prefix", &temp))
 				strncpy(gETHPrefix, temp, 32);
 			configGetInt(configOPL, "remember_last", &gRememberLastPlayed);
+#ifdef GSM
 			configGetInt(configOPL, "show_gsm", &gShowGSM);
+#endif
 			configGetInt(configOPL, "usb_mode", &gUSBStartMode);
 			configGetInt(configOPL, "hdd_mode", &gHDDStartMode);
 			configGetInt(configOPL, "eth_mode", &gETHStartMode);
 		configSetInt(configOPL, "vmode", gVMode);
 		configSetInt(configOPL, "vsync", gVSync);
 
+#ifdef GSM
 		configSetInt(configOPL, "enable_gsm", gEnableGSM);
 		configSetInt(configOPL, "gsmvmode", gGSMVMode);
 		configSetInt(configOPL, "gsm_x_offset", gGSMXOffset);
 		configSetInt(configOPL, "gsm_y_offset", gGSMYOffset);
 		configSetInt(configOPL, "gsmskipvideos", gGSMSkipVideos);
+#endif
 
 		configSetInt(configOPL, "eth_linkmode", gETHOpMode);
 		char temp[255];
 		configSetStr(configOPL, "usb_prefix", gUSBPrefix);
 		configSetStr(configOPL, "eth_prefix", gETHPrefix);
 		configSetInt(configOPL, "remember_last", gRememberLastPlayed);
+#ifdef GSM
 		configSetInt(configOPL, "show_gsm", gShowGSM);
+#endif
 		configSetInt(configOPL, "usb_mode", gUSBStartMode);
 		configSetInt(configOPL, "hdd_mode", gHDDStartMode);
 		configSetInt(configOPL, "eth_mode", gETHStartMode);
 	gDisableDebug = 0;
 	gEnableDandR = 0;
 	gRememberLastPlayed = 0;
+#ifdef GSM
 	gShowGSM = 0;
+#endif
 	gCheckUSBFragmentation = 1;
 	gUSBDelay = 3;
 	strncpy(gUSBPrefix, "", 32);
 	gVMode = RM_VMODE_AUTO;
 	gVSync = 1;
 
+#ifdef GSM
 	gEnableGSM = 0;
 	gGSMVMode = 0;
 	gGSMXOffset = 0;
 	gGSMYOffset = 0;
 	gGSMSkipVideos = 0;
+#endif
 }
 
 static void init(void) {
 	// handler for deffered menu updates
 	ioRegisterHandler(IO_MENU_UPDATE_DEFFERED, &menuDeferredUpdate);
 
+	InitConsoleRegionData();
+
 	// try to restore config
 	_loadConfig();
 
 #include "include/pad.h"
 #include "include/system.h"
 #include "include/ioman.h"
+#include "include/OSDHistory.h"
 #ifdef VMC
 typedef struct {
 	char VMC_filename[1024];
 	char gsm_config_str[256];
 #endif
 
+	//AddHistoryRecordUsingFullPath(filename); BUG: added history records are invalid (No filename entered and the record seems to be duplicated everywhere).
+
 	if (gExitPath[0] == '\0')
 		strncpy(gExitPath, "Browser", 32);
 
 	item->UID = 0;
 }
 
-image_cache_t* cacheInitCache(int userId, char* prefix, int isPrefixRelative, char* suffix, int count) {
+image_cache_t* cacheInitCache(int userId, const char* prefix, int isPrefixRelative, const char* suffix, int count) {
 	image_cache_t* cache = (image_cache_t*) malloc(sizeof(image_cache_t));
 	cache->userId = userId;
 	cache->count = count;
 	//gsKit_setup_tbw(texture); already done in gsKit_texture_upload
 }
 
-int texDiscoverLoad(GSTEXTURE* texture, char* path, int texId, short psm) {
+int texDiscoverLoad(GSTEXTURE* texture, const char* path, int texId, short psm) {
 	int rc = texPngLoad(texture, path, texId, psm);
 	/*
 	if (rc < 0) {
 	png_read_end(pngPtr, NULL);
 }
 
-int texPngLoad(GSTEXTURE* texture, char* path, int texId, short psm) {
+int texPngLoad(GSTEXTURE* texture, const char* path, int texId, short psm) {
 	texPrepare(texture, psm);
 	png_structp pngPtr = NULL;
 	png_infop infoPtr = NULL;
 		else
 			snprintf(filePath, 255, "%s.png", path);
 
-		file = fopen(filePath, "r");
+		file = fopen(filePath, "rb");
 		if (file == NULL)
 			return ERR_BAD_FILE;
 
 /// JPG SUPPORT ///////////////////////////////////////////////////////////////////////////////////////
 
 
-int texJpgLoad(GSTEXTURE* texture, char* path, int texId, short psm) {
+int texJpgLoad(GSTEXTURE* texture, const char* path, int texId, short psm) {
 	texPrepare(texture, GS_PSM_CT24);
 	int result = ERR_BAD_FILE;
 	jpgData *jpg = NULL;
-	char filePath[255];
+	char filePath[256];
 
 	if (texId != -1)
-		snprintf(filePath, 255, "%s%s.jpg", path, internalDefault[texId].name);
+		snprintf(filePath, sizeof(filePath), "%s%s.jpg", path, internalDefault[texId].name);
 	else
-		snprintf(filePath, 255, "%s.jpg", path);
-	FILE* file = fopen(filePath, "r");
+		snprintf(filePath, sizeof(filePath), "%s.jpg", path);
+	FILE* file = fopen(filePath, "rb");
 	if (file) {
 		jpg = jpgOpenFILE(file, JPG_NORMAL);
 		if (jpg != NULL) {
 
 static int nThemes = 0;
 static theme_file_t themes[THM_MAX_FILES];
-static char **guiThemesNames = NULL;
+static const char **guiThemesNames = NULL;
 
 #define TYPE_ATTRIBUTE_TEXT		0
 #define TYPE_STATIC_TEXT		1
 #define SIZING_CLIP			0
 #define SIZING_WRAP			1
 
-static char *elementsType[] = {
+static const char *elementsType[] = {
 	"AttributeText",
 	"StaticText",
 	"AttributeImage",
 	free(elem);
 }
 
-static mutable_text_t* initMutableText(char* themePath, config_set_t* themeConfig, theme_t* theme, char* name, int type, struct theme_element* elem,
-		char* value, char* alias, int displayMode, int sizingMode) {
-
+static mutable_text_t* initMutableText(const char* themePath, config_set_t* themeConfig, theme_t* theme, const char* name, int type, struct theme_element* elem, const char* value, const char* alias, int displayMode, int sizingMode) {
 	mutable_text_t* mutableText = (mutable_text_t*) malloc(sizeof(mutable_text_t));
 	mutableText->currentConfigId = 0;
 	mutableText->currentValue = NULL;
 		fntRenderString(elem->font, elem->posX, elem->posY, elem->aligned, elem->width, elem->height, mutableText->value, elem->color);
 }
 
-static void initStaticText(char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, char* name,
-		char* value) {
-
+static void initStaticText(const char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, const char* name) {
+	const char *value;
 	char elemProp[64];
 
 	snprintf(elemProp, 64, "%s_value", name);
 			// force refresh
 			mutableText->currentConfigId = config->uid;
 			mutableText->currentValue = NULL;
-			if (configGetStr(config, mutableText->value, &mutableText->currentValue)) {
+			if (configGetStr(config, mutableText->value, (const char**)&mutableText->currentValue)) {
 				if (mutableText->sizingMode == SIZING_WRAP)
 					fntFitString(elem->font, mutableText->currentValue, elem->width);
 			}
 	}
 }
 
-static void initAttributeText(char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, char* name,
-		char* attribute) {
-
+static void initAttributeText(const char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, const char* name) {
+	const char* attribute;
 	char elemProp[64];
 
 	snprintf(elemProp, 64, "%s_attribute", name);
 
 // Common functions for Image ///////////////////////////////////////////////////////////////////////////////////////////////
 
-static void findDuplicate(theme_element_t* first, char* cachePattern, char* defaultTexture, char* overlayTexture, mutable_image_t* target) {
+static void findDuplicate(theme_element_t* first, const char* cachePattern, const char* defaultTexture, const char* overlayTexture, mutable_image_t* target) {
 	theme_element_t* elem = first;
 	while (elem) {
 		if ((elem->type == TYPE_STATIC_IMAGE) || (elem->type == TYPE_ATTRIBUTE_IMAGE) || (elem->type == TYPE_GAME_IMAGE) || (elem->type == TYPE_BACKGROUND)) {
 	}
 }
 
-static image_texture_t* initImageTexture(char* themePath, config_set_t* themeConfig, char* name, char* imgName, int isOverlay) {
+static image_texture_t* initImageTexture(const char* themePath, config_set_t* themeConfig, const char* name, const char* imgName, int isOverlay) {
 	image_texture_t* texture = (image_texture_t*) malloc(sizeof(image_texture_t));
 	texPrepare(&texture->source, isOverlay ? GS_PSM_CT32 : GS_PSM_CT24);
 	texture->name = NULL;
 
-	char path[255];
-	snprintf(path, 255, "%s%s", themePath, imgName);
+	char path[256];
+	snprintf(path, sizeof(path), "%s%s", themePath, imgName);
 	if (texDiscoverLoad(&texture->source, path, -1, isOverlay ? GS_PSM_CT32 : GS_PSM_CT24) >= 0) {
 		int length = strlen(imgName) + 1;
 		texture->name = (char*) malloc(length * sizeof(char));
 	free(elem);
 }
 
-static mutable_image_t* initMutableImage(char* themePath, config_set_t* themeConfig, theme_t* theme, char* name, int type,
-		char* cachePattern, int cacheCount, char* defaultTexture, char* overlayTexture) {
-
+static mutable_image_t* initMutableImage(const char* themePath, config_set_t* themeConfig, theme_t* theme, const char* name, int type, const char* cachePattern, int cacheCount, const char* defaultTexture, const char* overlayTexture) {
 	mutable_image_t* mutableImage = (mutable_image_t*) malloc(sizeof(mutable_image_t));
 	mutableImage->currentUid = -1;
 	mutableImage->currentConfigId = 0;
 		rmDrawPixmap(&staticImage->defaultTexture->source, elem->posX, elem->posY, elem->aligned, elem->width, elem->height, elem->scaled, gDefaultCol);
 }
 
-static void initStaticImage(char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, char* name,
-		char* imageName) {
-
+static void initStaticImage(const char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, const char* name, const char* imageName) {
 	mutable_image_t* mutableImage = initMutableImage(themePath, themeConfig, theme, name, elem->type, NULL, 0, imageName, NULL);
 	elem->extended = mutableImage;
 	elem->endElem = &endMutableImage;
 	}
 }
 
-static void initGameImage(char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, char* name,
-		char* pattern, int count, char* texture, char* overlay) {
-
+static void initGameImage(const char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, const char* name, const char* pattern, int count, const char* texture, const char* overlay) {
 	mutable_image_t* mutableImage = initMutableImage(themePath, themeConfig, theme, name, elem->type, pattern, count, texture, overlay);
 	elem->extended = mutableImage;
 	elem->endElem = &endMutableImage;
 			attributeImage->currentUid = -1;
 			attributeImage->currentConfigId = config->uid;
 			attributeImage->currentValue = NULL;
-			configGetStr(config, attributeImage->cache->suffix, &attributeImage->currentValue);
+			configGetStr(config, attributeImage->cache->suffix, (const char**)&attributeImage->currentValue);
 		}
 		if (attributeImage->currentValue) {
 			int posZ = 0;
 		rmDrawPixmap(&attributeImage->defaultTexture->source, elem->posX, elem->posY, elem->aligned, elem->width, elem->height, elem->scaled, gDefaultCol);
 }
 
-static void initAttributeImage(char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, char* name) {
+static void initAttributeImage(const char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, const char* name) {
 	mutable_image_t* mutableImage = initMutableImage(themePath, themeConfig, theme, name, elem->type, NULL, 1, NULL, NULL);
 	elem->extended = mutableImage;
 	elem->endElem = &endMutableImage;
 	free(elem);
 }
 
-static theme_element_t* initBasic(char* themePath, config_set_t* themeConfig, theme_t* theme,
-		char* name,	int type, int x, int y, short aligned, int w, int h, short scaled, u64 color, int font) {
-
+static theme_element_t* initBasic(const char* themePath, config_set_t* themeConfig, theme_t* theme, const char* name, int type, int x, int y, short aligned, int w, int h, short scaled, u64 color, int font) {
 	int intValue;
 	unsigned char charColor[3];
-	char* temp;
+	const char* temp;
 	char elemProp[64];
 
 	theme_element_t* elem = (theme_element_t*) malloc(sizeof(theme_element_t));
 	guiDrawBGPlasma();
 }
 
-static void initBackground(char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, char* name,
-		char* pattern, int count, char* texture) {
-
+static void initBackground(const char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, const char* name, const char* pattern, int count, const char* texture) {
 	mutable_image_t* mutableImage = initMutableImage(themePath, themeConfig, theme, name, elem->type, pattern, count, texture, NULL);
 	elem->extended = mutableImage;
 	elem->endElem = &endMutableImage;
 	}
 }
 
-static void initItemsList(char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, char* name, char* decorator) {
+static void initItemsList(const char* themePath, config_set_t* themeConfig, theme_t* theme, theme_element_t* elem, const char* name, const char* decorator) {
 	char elemProp[64];
 
 	items_list_t* itemsList = (items_list_t*) malloc(sizeof(items_list_t));
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-static void validateGUIElems(char* themePath, config_set_t* themeConfig, theme_t* theme) {
+static void validateGUIElems(const char* themePath, config_set_t* themeConfig, theme_t* theme) {
 	// 1. check we have a valid Background elements
 	if ( !theme->mainElems.first || (theme->mainElems.first->type != TYPE_BACKGROUND) ) {
 		LOG("THEMES No valid background found for main, add default BG_ART\n");
 	}
 }
 
-static int addGUIElem(char* themePath, config_set_t* themeConfig, theme_t* theme, theme_elems_t* elems, char* type, char* name) {
-
+static int addGUIElem(const char* themePath, config_set_t* themeConfig, theme_t* theme, theme_elems_t* elems, const char* type, const char* name) {
 	int enabled = 1;
 	char elemProp[64];
 	theme_element_t* elem = NULL;
 		if (type) {
 			if (!strcmp(elementsType[TYPE_ATTRIBUTE_TEXT], type)) {
 				elem = initBasic(themePath, themeConfig, theme, name, TYPE_ATTRIBUTE_TEXT, 0, 0, ALIGN_CENTER, DIM_UNDEF, DIM_UNDEF, SCALING_RATIO, theme->textColor, theme->fonts[0]);
-				initAttributeText(themePath, themeConfig, theme, elem, name, NULL);
+				initAttributeText(themePath, themeConfig, theme, elem, name);
 			} else if (!strcmp(elementsType[TYPE_STATIC_TEXT], type)) {
 				elem = initBasic(themePath, themeConfig, theme, name, TYPE_STATIC_TEXT, 0, 0, ALIGN_CENTER, DIM_UNDEF, DIM_UNDEF, SCALING_RATIO, theme->textColor, theme->fonts[0]);
-				initStaticText(themePath, themeConfig, theme, elem, name, NULL);
+				initStaticText(themePath, themeConfig, theme, elem, name);
 			} else if (!strcmp(elementsType[TYPE_ATTRIBUTE_IMAGE], type)) {
 				elem = initBasic(themePath, themeConfig, theme, name, TYPE_ATTRIBUTE_IMAGE, 0, 0, ALIGN_CENTER, DIM_UNDEF, DIM_UNDEF, SCALING_RATIO, gDefaultCol, theme->fonts[0]);
 				initAttributeImage(themePath, themeConfig, theme, elem, name);
 	}
 }
 
-static int thmReadEntry(int index, char* path, char* separator, char* name, unsigned int mode) {
+static int thmReadEntry(int index, const char* path, const char* separator, const char* name, unsigned int mode) {
 	if (FIO_SO_ISDIR(mode) && strstr(name, "thm_")) {
 		theme_file_t* currTheme = &themes[nThemes + index];
 
 }
 
 /* themePath must contains the leading separator (as it is dependent of the device, we can't know here) */
-static int thmLoadResource(int texId, char* themePath, short psm, int useDefault) {
+static int thmLoadResource(int texId, const char* themePath, short psm, int useDefault) {
 	int success = -1;
 	GSTEXTURE* texture = &gTheme->textures[texId];
 
 		}
 
 		char fullPath[128];
-		char *fntFile;
+		const char *fntFile;
 		if (configGetStr(themeConfig, fntKey, &fntFile)) {
 			snprintf(fullPath, 128, "%s%s", themePath, fntFile);
 			int fntHandle = fntLoadFile(fullPath);
 	}
 }
 
-static void thmLoad(char* themePath) {
+static void thmLoad(const char* themePath) {
 	LOG("THEMES Load theme path=%s\n", themePath);
 	theme_t* curT = gTheme;
 	theme_t* newT = (theme_t*) malloc(sizeof(theme_t));
 	thmFree(curT);
 
 	// First start with busy icon
-	char* path = themePath;
+	const char* path = themePath;
 	int customBusy = 0;
 	for (i = LOAD0_ICON; i <= LOAD7_ICON; i++) {
 		if (thmLoadResource(i, path, GS_PSM_CT32, gTheme->useDefault) >= 0)
 		thmLoadResource(i, NULL, GS_PSM_CT32, 1);
 }
 
-static void thmRebuildGuiNames() {
+static void thmRebuildGuiNames(void) {
 	if (guiThemesNames)
 		free(guiThemesNames);
 
 	// build the languages name list
-	guiThemesNames = (char**) malloc((nThemes + 2) * sizeof(char**));
+	guiThemesNames = (const char**) malloc((nThemes + 2) * sizeof(char**));
 
 	// add default internal
 	guiThemesNames[0] = "<OPL>";
 	guiThemesNames[nThemes + 1] = NULL;
 }
 
-void thmAddElements(char* path, char* separator, int mode) {
+void thmAddElements(char* path, const char* separator, int mode) {
 	nThemes += listDir(path, separator, THM_MAX_FILES - nThemes, &thmReadEntry);
 	thmRebuildGuiNames();
 
-	char* temp;
+	const char* temp;
 	if (configGetStr(configGetByType(CONFIG_OPL), "theme", &temp)) {
 		LOG("THEMES Trying to set again theme: %s\n", temp);
 		if (thmSetGuiValue(thmFindGuiID(temp), 0))
 	}
 }
 
-void thmInit() {
+void thmInit(void) {
 	LOG("THEMES Init\n");
 	gTheme = NULL;
 
 	thmAddElements(gBaseMCDir, "/", -1);
 }
 
-void thmReinit(char* path) {
+void thmReinit(const char* path) {
 	thmLoad(NULL);
 	guiThemeID = 0;
 
 	thmRebuildGuiNames();
 }
 
-void thmReloadScreenExtents() {
+void thmReloadScreenExtents(void) {
 	rmGetScreenExtents(&screenWidth, &screenHeight);
 }
 
-char* thmGetValue() {
+const char* thmGetValue(void) {
 	return guiThemesNames[guiThemeID];
 }
 
 	return 0;
 }
 
-int thmGetGuiValue() {
+int thmGetGuiValue(void) {
 	return guiThemeID;
 }
 
-int thmFindGuiID(char* theme) {
+int thmFindGuiID(const char* theme) {
 	if (theme) {
 		int i = 0;
 		for (; i < nThemes; i++) {
 	return 0;
 }
 
-char **thmGetGuiList() {
+const char **thmGetGuiList(void) {
 	return guiThemesNames;
 }
 
-void thmEnd() {
+void thmEnd(void) {
 	thmFree(gTheme);
 
 	int i = 0;
 
 	fioDclose(fd);
 
-	char *altStartup = NULL;
+	const char *altStartup = NULL;
 	if (configGetStr(configSet, CONFIG_ITEM_ALTSTARTUP, &altStartup))
 		strncpy(filename, altStartup, 32);
 	else
 #include "include/ioman.h"
 #include <io_common.h>
 #include <string.h>
-#include "malloc.h"
-#include "fileio.h"
+#include <malloc.h>
+#include <fileio.h>
+#include <osd_config.h>
 
 extern void *icon_sys;
 extern int size_icon_sys;
 		fioDclose(fd);
 }
 
-int listDir(char* path, char* separator, int maxElem,
-		int (*readEntry)(int index, char *path, char* separator, char* name, unsigned int mode)) {
+int listDir(char* path, const char* separator, int maxElem,
+		int (*readEntry)(int index, const char *path, const char* separator, const char* name, unsigned int mode)) {
 	int fdDir, index = 0;
 	if (checkFile(path, O_RDONLY)) {
 		fio_dirent_t record;
 char toHex(int digit) {
 	return htab[digit & 0x0F];
 }
+
+enum CONSOLE_REGIONS{
+	CONSOLE_REGION_INVALID	= -1,
+	CONSOLE_REGION_JAPAN	= 0,
+	CONSOLE_REGION_USA,	//USA and HK/SG.
+	CONSOLE_REGION_EUROPE,
+	CONSOLE_REGION_CHINA,
+
+	CONSOLE_REGION_COUNT
+};
+
+static short int ConsoleRegion=CONSOLE_REGION_INVALID;
+static char SystemDataFolderPath[]="BRDATA-SYSTEM";
+static char SystemFolderLetter='R';
+
+static void UpdateSystemPaths(void){
+	char regions[CONSOLE_REGION_COUNT]={'I', 'A', 'E', 'C'};
+
+	SystemFolderLetter=regions[ConsoleRegion];
+	SystemDataFolderPath[1]=SystemFolderLetter;
+}
+
+int InitConsoleRegionData(void){
+	int result;
+	char romver[16];
+
+	if((result=ConsoleRegion)<0){
+		GetRomName(romver);
+
+		switch(romver[4]){
+			case 'C':
+				ConsoleRegion=CONSOLE_REGION_CHINA;
+				break;
+			case 'E':
+				ConsoleRegion=CONSOLE_REGION_EUROPE;
+				break;
+			case 'H':
+			case 'A':
+				ConsoleRegion=CONSOLE_REGION_USA;
+				break;
+			case 'J':
+				ConsoleRegion=CONSOLE_REGION_JAPAN;
+		}
+
+		result=ConsoleRegion;
+
+		UpdateSystemPaths();
+	}
+
+	return result;
+}
+
+const char *GetSystemDataPath(void){
+	return SystemDataFolderPath;
+}
+
+char GetSystemFolderLetter(void){
+	return SystemFolderLetter;
+}