Fix fifo ...

* FIFO on arm7 appears to now work as intended.
* GBA mode switch funcition remains broken.
* Default GBA_Exploader.ini file now created if one is not present.
* Moved GBA_File struct to ctrl_tble and removed duplicate from main.c.
This was causing issues where I would forget to update both when I
removed the now unused Alias char array. All code now shares the single
instance which will prevent this issue should this struct need to be
updated in the future.
This commit is contained in:
ApacheThunder 2024-05-08 15:24:51 -05:00
parent fd132bb8ab
commit 11ea610150
21 changed files with 680 additions and 303 deletions

View File

@ -9,7 +9,7 @@ export TARGET := GBA_ExpLoader
export TOPDIR := $(CURDIR)
export VERSION_MAJOR := 0
export VERSION_MINOR := 57
export VERSION_MINOR := 58
export VERSTRING := $(VERSION_MAJOR).$(VERSION_MINOR)
# GMAE_ICON is the image used to create the game icon, leave blank to use default rule

View File

@ -22,18 +22,15 @@ DATA :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
# ARCH := -mthumb -mthumb-interwork
ARCH := -mthumb-interwork
CFLAGS := -g -Wall -O2 \
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
-ffast-math \
$(ARCH)
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
-ffast-math \
$(ARCH)
# CFLAGS += $(INCLUDE) -DARM7
CFLAGS += $(INCLUDE) -DARM7 -fsigned-char
CFLAGS += $(INCLUDE) -DARM7
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
CXXFLAGS := $(CFLAGS)
ASFLAGS := -g $(ARCH)
@ -41,7 +38,7 @@ LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,-Map,$(notdir $*).map
# LDFLAGS = -specs=ds_arm7_iwram.specs -g $(ARCH) -Wl,-Map,$(notdir $*).map
LIBS := -lnds7
LIBS := -lnds7
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View File

@ -0,0 +1,18 @@
#ifdef __cplusplus
extern "C" {
#endif
void LinkReset_ARM7();
#ifdef __cplusplus
}
#endif
/*
--------------------------
EDIY Studio
http://www.gbalink.net
http://www.ds-link.net
--------------------------
*/

View File

@ -0,0 +1,20 @@
.TEXT
.ARM
@---------------------------------------------------------------------------------------
.GLOBAL LinkReset_ARM7
.func LinkReset_ARM7
@---------------------------------------------------------------------------------------
LinkReset_ARM7:
MOV R12,#0x2800000
LDR R1,[R12,#-0x1DC]
ADD R1,R1,#0x1FC
CMP R12, R1
SUBEQ R15,R12,#0x700000
BX LR
.endfunc
.end

View File

@ -28,6 +28,16 @@
---------------------------------------------------------------------------------*/
#include <nds.h>
#include <stdlib.h>
#include <string.h>
#include "linkreset_arm7.h"
volatile bool switchedMode = false;
extern void ret_menu7_R4(void);
extern void ret_menu7_Gen(void);
extern void ret_menu7_mse(void);
void gbaMode() {
vu32 vr;
@ -48,12 +58,67 @@ void gbaMode() {
while(1);
}
static void prepairReset() {
vu32 vr;
u32 i;
powerOn(POWER_SOUND);
for(i = 0x040000B0; i < (0x040000B0+0x30); i+=4)*((vu32*)i) = 0;
REG_IME = IME_DISABLE;
REG_IE = 0;
REG_IF = ~0;
for(vr = 0; vr < 0x100; vr++); // Wait ARM9
swiSoftReset();
}
volatile bool exitflag = false;
void powerButtonCB() { exitflag = true; }
void VblankHandler(void) {
void fifoCheckHandler() {
if (!switchedMode) {
if(fifoCheckValue32(FIFO_USER_01)) {
switchedMode = true;
gbaMode();
} else if (fifoCheckValue32(FIFO_USER_02)) {
switchedMode = true;
ret_menu7_R4();
} else if (fifoCheckValue32(FIFO_USER_03)) {
switchedMode = true;
LinkReset_ARM7();
} else if (fifoCheckValue32(FIFO_USER_04)) {
switchedMode = true;
ret_menu7_Gen();
} else if (fifoCheckValue32(FIFO_USER_05)) {
switchedMode = true;
prepairReset();
}
}
/*u32 fifo;
if(!(REG_IPC_FIFO_CR & IPC_FIFO_RECV_EMPTY)) {
fifo = REG_IPC_FIFO_RX;
if(fifo == IPC_CMD_GBAMODE)gbaMode();
if(fifo == IPC_CMD_SLOT2)prepairReset();
if(fifo == IPC_CMD_TURNOFF) {
PM_SetControl(1<<6);
while(1);
}
if(fifo == IPC_CMD_SR_R4TF)ret_menu7_R4();
if(fifo == IPC_CMD_SR_DLMS)LinkReset_ARM7();
if(fifo == IPC_CMD_SR_GEN)ret_menu7_Gen();
if(fifo == IPC_CMD_SR_MSE)ret_menu7_mse();
}*/
}
void VblankHandler(void) {
fifoCheckHandler();
// Wifi_Update();
}
@ -63,8 +128,7 @@ void VcountHandler() { inputGetAndSend(); }
int main() {
readUserSettings();
ledBlink(0);
bool switchedMode = false;
irqInit();
// Start the RTC tracking IRQ
initClockIRQ();
@ -88,14 +152,7 @@ int main() {
setPowerButtonCB(powerButtonCB);
// Keep the ARM7 mostly idle
while(1) {
if(fifoCheckValue32(FIFO_USER_01) && !switchedMode) {
switchedMode = true;
gbaMode();
}
swiWaitForVBlank();
}
while(1)swiWaitForVBlank();
return 0;
}

155
arm7/source/ret_menu7_Gen.c Normal file
View File

@ -0,0 +1,155 @@
/***********************************************************
Arm7 Soft rest for General purpose
by Rudolph (<EFBFBD>cé)
***************************************************************/
#include <nds.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARM7_PROG (0x03810000 - 0xA00)
#define SOUND_CR REG_SOUNDCNT
typedef void (* FN_MEDIUM_ARM7)(void);
FN_MEDIUM_ARM7 _menu7_Gen;
extern void _menu7_Gen_s();
void ret_menu7_Gen() {
u32 *adr;
u32 *buf;
u32 i;
while((*(vu32*)0x027FFDFC) != 0x027FFDF8) { // Timing adjustment with ARM9
vu32 w;
for(w=0;w<0x100;w++);
}
REG_IME = IME_DISABLE; // Disable interrupts
REG_IF = REG_IF; // Acknowledge interrupt
// REG_IME = 0;
for (i = 0x04000400; i < 0x04000500; i+=4)*((u32*)i) = 0;
SOUND_CR = 0;
for(i = 0x040000B0; i < (0x040000B0+0x30); i+=4)*((vu32*)i) = 0;
for(i = 0x04000100; i < 0x04000110; i+=2)*((u16*)i) = 0;
//switch to user mode
asm("mov r0, #0x1F");
asm("msr cpsr, r0");
adr = (u32*)ARM7_PROG;
buf = (u32*)_menu7_Gen_s;
for(i = 0; i < 0x200/4; i++) {
*adr = *buf;
adr++;
buf++;
}
_menu7_Gen = (FN_MEDIUM_ARM7)ARM7_PROG;
_menu7_Gen();
while(1);
}
void _menu7_Gen_s() {
u32 *adr;
u32 *bufh, *buf7, *buf9;
u32 siz;
u32 i;
u32 *arm9s, *arm9e;
u32 *arm7s, *arm7e;
bufh = (u32*)(*(vu32*)0x027FFDF4);
adr = (u32*)0x027FFE00;
for(i = 0; i < 512/4; i++) { // Header
*adr = *bufh;
adr++;
bufh++;
}
buf9 = bufh;
buf7 = buf9 + ((*(vu32*)0x027FFE2C) / 4);
adr = (u32*)(*(vu32*)0x027FFE38);
siz = (*(vu32*)0x027FFE3C);
for(i = 0; i < siz/4; i++) { // ARM7
*adr = *buf7;
adr++;
buf7++;
}
arm7e = adr;
adr = (u32*)(*(vu32*)0x027FFE28);
siz = (*(vu32*)0x027FFE2C);
if(adr < buf9) { // ARM9
for(i = 0; i < siz/4; i++) {
*adr = *buf9;
adr++;
buf9++;
}
arm9e = adr;
} else {
adr += (siz/4 - 1);
buf9 += (siz/4 - 1);
arm9e = adr + 1;
for(i = 0; i < siz/4; i++) {
*adr = *buf9;
adr--;
buf9--;
}
}
arm7s = (u32*)(*(vu32*)0x027FFE38);
if(arm7s > (u32*)0x023FF800)
arm7s = (u32*)0x023FF800;
arm9s = (u32*)(*(vu32*)0x027FFE28);
if(arm9s > arm7s) {
adr = arm9s;
arm9s = arm7s;
arm7s = adr;
adr = arm9e;
arm9e = arm7e;
arm7e = adr;
}
adr = (u32*)0x02000000;
while(adr < arm9s) {
*adr = 0x00000000;
adr++;
}
while(arm9e < arm7s) {
*arm9e = 0x00000000;
arm9e++;
}
while(arm7e < (u32*)0x023FF800) {
*arm7e = 0x00000000;
arm7e++;
}
REG_IE = 0;
REG_IF = ~0;
(*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version
(*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version
REG_POWERCNT = 1; //turn off power to stuffs
*(vu32*)0x027FFDFC = *(vu32*)0x027FFE24;
asm("swi 0x00"); // JUMP 0x027FFE34
while(1);
}

160
arm7/source/ret_menu7_R4.c Normal file
View File

@ -0,0 +1,160 @@
/***********************************************************
by Rudolph (<EFBFBD>cé)
2007/05/24 First release
2007/05/27 Timing adjustment with ARM9
------------------------------------------------------------
SoftwareReset Routines for R4DS or M3SimplyDS.
Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:
Only the Homebrew application can be used.
It is not possible to use it by a business purpose.
This software is made based on information obtained
by Reverse engineering.
Please use that at once when a source code that is
more formal than the official is open to the public.
***************************************************************/
#include <nds.h>
//#include <nds/registers_alt.h> // devkitPror20
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CARD_COMMAND REG_CARD_COMMAND
#define CARD_CR1H REG_AUXSPICNTH
#define CARD_CR2 REG_ROMCTRL
#define CARD_DATA_RD REG_CARD_DATA_RD
static int _set_r4menu()
{
u32 add;
add = (*(vu32*)0x027FFE18);
while(CARD_CR2 & CARD_BUSY);
CARD_CR1H = 0xC0;
CARD_COMMAND[0] = 0xB4;
CARD_COMMAND[1] = (add >> 24) & 0xFF;
CARD_COMMAND[2] = (add >> 16) & 0xFF;
CARD_COMMAND[3] = (add >> 8) & 0xFF;
CARD_COMMAND[4] = add & 0xFF;
// CARD_COMMAND[5] = 0x00;
// CARD_COMMAND[6] = 0x00;
// CARD_COMMAND[7] = 0x00;
CARD_CR2 = 0xA7586000;
while(!(CARD_CR2 & CARD_DATA_READY));
return(CARD_DATA_RD);
}
static int _read_r4menu(char *buf, u32 blk)
{
int s = 0;
u32 *buf32;
buf32 = (u32*)buf;
blk *= 2;
do {
while(CARD_CR2 & CARD_BUSY);
CARD_CR1H = 0xC0;
CARD_COMMAND[0] = 0xB6;
CARD_COMMAND[1] = (blk >> 16) & 0xFF;
CARD_COMMAND[2] = (blk >> 8) & 0xFF;
CARD_COMMAND[3] = blk & 0xFF;
CARD_COMMAND[4] = 0x00;
// CARD_COMMAND[5] = 0x00;
// CARD_COMMAND[6] = 0x00;
// CARD_COMMAND[7] = 0x00;
CARD_CR2 = 0xA7586000;
while(!(CARD_CR2 & CARD_DATA_READY));
} while(CARD_DATA_RD);
while(CARD_CR2 & CARD_BUSY);
CARD_CR1H = 0xC0;
CARD_COMMAND[0] = 0xBF;
CARD_COMMAND[1] = (blk >> 16) & 0xFF;
CARD_COMMAND[2] = (blk >> 8) & 0xFF;
CARD_COMMAND[3] = blk & 0xFF;
CARD_COMMAND[4] = 0x00;
// CARD_COMMAND[5] = 0x00;
// CARD_COMMAND[6] = 0x00;
// CARD_COMMAND[7] = 0x00;
CARD_CR2 = 0xA1586000;
do {
while(!(CARD_CR2 & CARD_DATA_READY));
*buf32 = CARD_DATA_RD;
buf32++;
s += 4;
} while(CARD_CR2 & CARD_BUSY);
return(s);
}
void ret_menu7_R4()
{
char *adr;
u32 blk, siz;
u32 i;
u32 *mem;
REG_IME = 0;
REG_IE = 0;
REG_IF = REG_IF;
REG_IPC_SYNC = 0;
DMA0_CR = 0;
DMA1_CR = 0;
DMA2_CR = 0;
DMA3_CR = 0;
while((*(vu32*)0x027FFDFC) != 0x027FFDF8); // Timing adjustment with ARM9
mem = (u32*)0x02000000;
for(i = 0; i < 0x3FF800/4; i++) {
*mem = 0x00000000;
mem++;
}
// memset((u8*)0x2000000, 0x00, 0x3FF800);
while(_set_r4menu());
adr = (char*)0x027FFE00;
_read_r4menu(adr, 0); // Header
blk = (*(vu32*)0x027FFE20) / 512;
adr = (char*)(*(vu32*)0x027FFE28);
siz = (*(vu32*)0x027FFE2C);
for(i = 0; i < siz; i += 512) { // ARM9
_read_r4menu(adr, blk);
blk++;
adr += 512;
}
blk = (*(vu32*)0x027FFE30) / 512;
adr = (char*)(*(vu32*)0x027FFE38);
siz = (*(vu32*)0x027FFE3C);
for(i = 0; i < siz; i += 512) { // ARM7
_read_r4menu(adr, blk);
blk++;
adr += 512;
}
*(vu32*)0x027FFDFC = *(vu32*)0x027FFE24;
asm("swi 0x00"); // JUMP 0x027FFE34
while(1);
}

View File

@ -0,0 +1,50 @@
/***********************************************************
Arm7 Soft rest for reset.mse
by Rudolph (<EFBFBD>cé)
***************************************************************/
#include <nds.h>
//#include <nds/registers_alt.h> // devkitPror20
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SOUND_CR REG_SOUNDCNT
void ret_menu7_mse() {
u32 i;
while(*((vu32*)0x027FFDFC) != 0x06000000) { // Timing adjustment with ARM9
vu32 w;
for(w=0;w<0x100;w++);
}
REG_IME = IME_DISABLE; // Disable interrupts
REG_IF = REG_IF; // Acknowledge interrupt
for (i = 0x04000400; i < 0x04000500; i+=4)*((u32*)i) = 0;
SOUND_CR = 0;
for(i = 0x040000B0; i < (0x040000B0+0x30); i+=4)*((vu32*)i) = 0;
for(i = 0x04000100; i < 0x04000110; i+=2)*((u16*)i) = 0;
//switch to user mode
asm("mov r0, #0x1F");
asm("msr cpsr, r0");
REG_IE = 0;
REG_IF = ~0;
(*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version
(*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version
REG_POWERCNT = 1; //turn off power to stuffs
*((vu32*)0x027FFE34) = *((vu32*)0x027FFDFC); // Bootloader start address
// asm("swi 0x00"); // JUMP 0x027FFE34
swiSoftReset();
while(1);
}

View File

@ -16,9 +16,7 @@ include $(DEVKITARM)/ds_rules
# all directories are relative to this makefile
#---------------------------------------------------------------------------------
BUILD := build
# SOURCES := source fonts source/tarosa source/card
# INCLUDES := include build source/tarosa source/card
SOURCES := source data source/tarosa
SOURCES := source source/tarosa
INCLUDES := include build source/tarosa
DATA := data
STATICLIBS :=
@ -26,12 +24,12 @@ STATICLIBS :=
# options for code generation
#---------------------------------------------------------------------------------
# $(ARCH) $(INCLUDE) -DARM9 -D_LegacyCardLib
ARCH := -mthumb-interwork
ARCH := -mthumb -mthumb-interwork -march=armv5te -mtune=arm946e-s
CFLAGS := -g -Wall -O2 \
$(ARCH) $(INCLUDE) -DARM9
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=dsi_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project

View File

@ -12,8 +12,10 @@ struct ini_file ini;
extern u8 *rwbuf;
void GBA_ini()
{
extern u8 defaultSettings[];
extern u8 defaultSettingsEnd[];
void GBA_ini() {
FILE *fini;
int len, p, s;
char key[20];
@ -22,22 +24,28 @@ void GBA_ini()
strcpy(ini.save_dir, "/GBA_SAVE");
strcpy(ini.sign_dir, "/GBA_SIGN");
fini = fopen("/GBA_ExpLoader.ini", "rb");
if(fini == NULL) {
mkdir(ini.save_dir, 0777);
mkdir(ini.sign_dir, 0777);
if(access("/GBA_ExpLoader.ini", F_OK) == 0) {
fini = fopen("/GBA_ExpLoader.ini", "rb");
if(access(ini.save_dir, F_OK) != 0)mkdir(ini.save_dir, 0777);
if(access(ini.sign_dir, F_OK) != 0)mkdir(ini.sign_dir, 0777);
} else {
fini = fopen("/GBA_ExpLoader.ini", "wb");
if (fini) {
fwrite(defaultSettings, (defaultSettingsEnd - defaultSettings), 1, fini);
fclose(fini);
}
if(access(ini.save_dir, F_OK) != 0)mkdir(ini.save_dir, 0777);
if(access(ini.sign_dir, F_OK) != 0)mkdir(ini.sign_dir, 0777);
return;
}
len = fread(rwbuf, 1, 0x1000, fini);
p = 0;
while(p < len) {
if(rwbuf[p] == '#' || rwbuf[p] == '!') {
while(p < len) {
if(rwbuf[p] == 0x0A)
break;
if(rwbuf[p] == 0x0A)break;
p++;
}
p++;

View File

@ -10,29 +10,28 @@
#include "GBA_ini.h"
#include "ctrl_tbl.h"
struct ctrl_tbl ctrl;
struct ctrl_tbl ctrl;
#define SRAM_ADDR 0x0A000000
#define SRAM_ADDR 0x0A000000
extern int carttype;
extern int carttype;
#ifdef __cplusplus
extern "C" {
#endif
extern void _RamPG(void);
extern void _RamSave(int bnk);
extern void _RamPG(void);
extern void _RamSave(int bnk);
#ifdef __cplusplus
}
#endif
void ctrl_get()
{
FILE *exp;
char expfile[64];
void ctrl_get() {
FILE *exp;
char expfile[64];
memset((u8*)&ctrl, 0, sizeof(struct ctrl_tbl));
@ -51,11 +50,9 @@ void ctrl_get()
}
}
void ctrl_set()
{
FILE *exp;
char expfile[64];
void ctrl_set() {
FILE *exp;
char expfile[64];
if(carttype != 5) {
_RamPG();

View File

@ -1,26 +1,32 @@
struct ctrl_tbl {
u8 sign[128];
u16 mode;
u8 save_flg[2];
u32 save_siz[2];
char filer[116];
u8 sav_nam[2][512];
u8 path[256];
struct GBA_File {
char filename[512];
char gametitle[13];
char gamecode[5];
u32 type;
u32 filesize;
};
extern struct ctrl_tbl ctrl;
struct ctrl_tbl {
u8 sign[128];
u16 mode;
u8 save_flg[2];
u32 save_siz[2];
char filer[116];
u8 sav_nam[2][512];
u8 path[256];
};
extern struct ctrl_tbl ctrl;
#ifdef __cplusplus
extern "C" {
#endif
extern void ctrl_get();
extern void ctrl_set();
extern void ctrl_get();
extern void ctrl_set();
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,6 @@
.arm
.global defaultSettings, defaultSettingsEnd
defaultSettings: .incbin "../include/defaultSettings.bin"
defaultSettingsEnd:

View File

@ -58,15 +58,7 @@ extern "C" {
extern char curpath[];
extern int sortfile[];
struct GBA_File {
u32 type;
char filename[512];
u32 filesize;
char gametitle[13];
char gamecode[5];
};
extern int sortfile[];
extern struct GBA_File fs[];
extern char tbuf[];
@ -469,9 +461,19 @@ int checkFlashID() {
if(carttype == 0) {
ewin = cehck_EWIN();
if(ewin > 0)carttype = 3 + ewin;
if(ewin > 0) {
carttype = 3 + ewin;
} else {
#ifdef _DEBUG
FILE *testFile = fopen("/gbacardID.bin", "wb");
if (testFile) {
fwrite((void*)id, 4, 1, testFile);
fclose(testFile);
}
#endif
}
}
return(carttype);
}
@ -485,8 +487,7 @@ bool checkSRAM_cnf() {
ctrl_get();
for(i = 0; ctrl.sign[i] != 0; i++) {
if(ctrl.sign[i] != Rudolph[i])
break;
if(ctrl.sign[i] != Rudolph[i])break;
}
// _RamSave(0);
@ -952,32 +953,23 @@ int writeFileToRam(int sel) {
// } else writeSramToFile(savName);
// if((fs[sel].Alias[strlen(fs[sel].Alias) - 3] != 'G') || (fs[sel].Alias[strlen(fs[sel].Alias) - 3] != 'g')) {
if((fs[sel].filename[strlen(fs[sel].filename) - 3] != 'G') || (fs[sel].filename[strlen(fs[sel].filename) - 3] != 'g')) {
gba = false;
} else {
gba = true;
}
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) {
if(carttype == 3)
SetRompage(0x300 - 3);
else SetRompage(384 - 3);
if(carttype == 3) { SetRompage(0x300 - 3); } else { SetRompage(384 - 3); }
OpenNorWrite();
}
// savesize = gba_check(gbaFile, fs[sel].filesize, rwbuf, 0x100000);
// if(savesize == 0)
// savesize = 0x8000;
// if(savesize == 0)savesize = 0x8000;
dsp_bar(2, -1);
@ -989,8 +981,7 @@ int writeFileToRam(int sel) {
dsp_bar(2, siz * 100 / fs[sel].filesize);
if(siz == 0 && gba)
header_rep(rwbuf);
if(siz == 0 && gba)header_rep(rwbuf);
savesize = gba_check_Ram1(rwbuf, 0x100000, fs[sel].filesize, siz);
@ -1011,27 +1002,18 @@ int writeFileToRam(int sel) {
// }
// getSaveFilename(sel, savName);
if(cmd >= 0)
writeSramFromFile(savName);
else blankSRAM(savName);
if(cmd >= 0) { writeSramFromFile(savName); } else { blankSRAM(savName); }
dsp_bar(-1, 100);
if(carttype < 4)
CloseNorWrite();
if(carttype < 4)CloseNorWrite();
_RamSave(0);
if(carttype >= 4) {
if(carttype == 6)
Close_M3();
else
Close_EWIN();
if(carttype == 6) { Close_M3(); } else { Close_EWIN(); }
}
if(carttype == 3)
SetRompage(0x300);
if(carttype <= 2)
SetRompage(384);
if(carttype == 3)SetRompage(0x300);
if(carttype <= 2)SetRompage(384);
return(0);
}
@ -1140,7 +1122,7 @@ void FileListGBA() {
dirent* pent = readdir(dir);
if(pent == NULL)break;
stat(pent->d_name, &st);
if ((((string)pent->d_name).compare(".") == 0) || ((st.st_mode & S_IFMT) == S_IFDIR) || nameEndsWith(pent->d_name, GBAEXT) || nameEndsWith(pent->d_name, BINEXT)) {
if (((st.st_mode & S_IFMT) == S_IFDIR) || 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;

9
arm9/source/graphics.s Normal file
View File

@ -0,0 +1,9 @@
.arm
.global unicode_ank_bin, unicode_l2u_bin, unicode_u2l_bin, shinonome_bin, shinonomeank_bin
unicode_ank_bin: .incbin "../graphics/unicode_ank.bin"
unicode_l2u_bin: .incbin "../graphics/unicode_l2u.bin"
unicode_u2l_bin: .incbin "../graphics/unicode_u2l.bin"
shinonome_bin: .incbin "../graphics/shinonome.bin"
shinonomeank_bin: .incbin "../graphics/shinonomeank.bin"

View File

@ -21,65 +21,49 @@
---------------------------------------------------------------------------------*/
#include "nds.h"
#include <nds/arm9/console.h> //basic print funcionality
//#include <nds/registers_alt.h>
// #include <nds/jtypes.h>
#include <nds/ndstypes.h>
#include <nds/fifocommon.h>
#include <nds/fifomessages.h>
#include <fat.h>
#include <sys/dir.h>
#include <sys/iosupport.h>
// #include "fatfile.h"
// #include <sys/iosupport.h>
#include <nds/arm9/dldi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "disc_io.h"
//#include "gba_nds_fat.h"
//extern LPIO_INTERFACE active_interface;
#include "maindef.h"
#include "dsCard.h"
#include "GBA_ini.h"
#include "ctrl_tbl.h"
//#include "ram.h"
#include "memcleaner.h"
#include "linkreset_arm9.h"
//#include "unicode.h"
#include "skin.h"
#include "message.h"
#include "tarosa/tarosa_Graphic.h"
#include "tarosa/tarosa_Shinofont.h"
extern uint16* MainScreen;
extern uint16* SubScreen;
//uint16* MainScreen = VRAM_A;
//uint16* SubScreen = (uint16*)BG_TILE_RAM_SUB(1);
#define BG_256_COLOR (BIT(7))
#define BG_256_COLOR (BIT(7))
#define VERSTRING "v0.58"
int numFiles = 0;
int numGames = 0;
char curpath[256];
char curpath[256];
int sortfile[200];
struct GBA_File {
char Alias[13];
u32 type;
char filename[512];
u32 filesize;
char gametitle[13];
char gamecode[5];
};
struct GBA_File fs[200];
char tbuf[512];
char filename[512];
struct GBA_File fs[200];
char tbuf[512];
char filename[512];
u8 *rwbuf;
@ -90,19 +74,16 @@ u8 *rwbuf;
#define IPC_CMD_SR_DLMS 12
#define IPC_CMD_SR_GEN 13
extern int carttype;
void Vblank() { }
// void Vblank() { }
// void FIFOInit() { REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR; }
// void FIFOSend(u32 val) { REG_IPC_FIFO_TX = val; }
u32 inp_key()
{
u32 inp_key() {
u32 ky;
while(1) {
@ -121,19 +102,19 @@ u32 inp_key()
}
extern void ret_menu9_R4(void);
extern bool ret_menu_chk(void);
extern bool ret_menu9_Gen(void);
extern void ret_menu9_GENs(void);
extern void ret_menu9_R4(void);
extern bool ret_menu_chk(void);
extern bool ret_menu9_Gen(void);
extern void ret_menu9_GENs(void);
void turn_off(int cmd) {
if(cmd == 0) { // 電源断
// FIFOSend(IPC_CMD_TURNOFF);
systemShutDown();
}
/*if(cmd == 1) { // R4 Soft Reset
if(cmd == 1) { // R4 Soft Reset
// FIFOSend(IPC_CMD_SR_R4TF);
fifoSendValue32(FIFO_USER_02, 1);
REG_IME = 0;
REG_IE = 0;
REG_IF = REG_IF;
@ -147,14 +128,16 @@ void turn_off(int cmd) {
ret_menu9_R4();
}
if(cmd == 2) { // DSLink Soft Reset
FIFOSend(IPC_CMD_SR_DLMS);
// FIFOSend(IPC_CMD_SR_DLMS);
fifoSendValue32(FIFO_USER_03, 1);
LinkReset_ARM9();
}
if(cmd == 3) { // General purpose Soft Reset
ret_menu9_Gen();
FIFOSend(IPC_CMD_SR_GEN);
fifoSendValue32(FIFO_USER_04, 1);
// FIFOSend(IPC_CMD_SR_GEN);
ret_menu9_GENs();
}*/
}
while(1);
}
@ -166,15 +149,21 @@ void gba_frame() {
u16 *pDstBuf1;
u16 *pDstBuf2;
ret = LoadSkin(2, "/gbaframe.bmp");
if(ret) return;
if (access("/gbaframe.bmp", F_OK) == 0) {
ret = LoadSkin(2, "/gbaframe.bmp");
if(ret)return;
}
sprintf(tbuf, "%s/gbaframe.bmp", ini.sign_dir);
ret = LoadSkin(2, tbuf);
if(ret) return;
if (access(tbuf, F_OK) == 0) {
ret = LoadSkin(2, tbuf);
if(ret)return;
}
ret = LoadSkin(2, "/_system_/gbaframe.bmp");
if(ret) return;
if (access("/_system_/gbaframe.bmp", F_OK) == 0) {
ret = LoadSkin(2, "/_system_/gbaframe.bmp");
if(ret)return;
}
pDstBuf1 = (u16*)0x06000000;
pDstBuf2 = (u16*)0x06020000;
@ -199,6 +188,7 @@ static void resetToSlot2() {
sysSetCartOwner(BUS_OWNER_ARM7); // ARM7 has access to GBA cart
// FIFOSend(IPC_CMD_SLOT2);
fifoSendValue32(FIFO_USER_05, 1);
for(vr = 0; vr < 0x20000; vr++); // Wait ARM7
@ -209,10 +199,10 @@ static void resetToSlot2() {
void gbaMode() {
if(strncmp(GBA_HEADER.gamecode, "PASS", 4) == 0) {
/*if(strncmp(GBA_HEADER.gamecode, "PASS", 4) == 0) {
resetARM9Memory();
resetToSlot2();
}
}*/
videoSetMode(0);
videoSetModeSub(0);
@ -222,8 +212,9 @@ void gbaMode() {
// vramSetMainBanks(VRAM_A_MAIN_BG, VRAM_B_MAIN_BG, VRAM_C_ARM7, VRAM_D_ARM7);
if(PersonalData->gbaScreen) { lcdMainOnBottom(); } else { lcdMainOnTop(); }
// FIFOSend(IPC_CMD_GBAMODE);
fifoSendValue32(FIFO_USER_01, 1);
gba_frame();
@ -231,8 +222,7 @@ void gbaMode() {
fifoSendValue32(FIFO_USER_01, 1);
sysSetBusOwners(ARM7_OWNS_CARD, ARM7_OWNS_ROM);
REG_IME = 0;
while(1);
while(1)swiWaitForVBlank();
}
@ -571,7 +561,9 @@ void _gba_dsp(int no, int mod, int x, int y) {
sprintf(tbuf, "Size: %dKB (%s %s)", (int)fs[sn].filesize / 1024, fs[sn].gametitle, fs[sn].gamecode);
ShinoPrint_SUB( SubScreen, 4*6, 5*12, (u8 *)tbuf, 1, 0, 0 );
}
} else ShinoPrint( MainScreen, x*6, y*12, (u8 *)tbuf, RGB15(0,0,0), RGB15(31,31,31), 1);
} else {
ShinoPrint( MainScreen, x*6, y*12, (u8 *)tbuf, RGB15(0,0,0), RGB15(31,31,31), 1);
}
}
@ -621,19 +613,22 @@ void _gba_sel_dsp(int no, int yc, int mod) {
if(carttype < 3) {
ShinoPrint_SUB( SubScreen, 2*6, 14*12+6, (u8 *)t_msg[5], 1, 0, 1);
} else {
if(r4tf)
if(r4tf) {
ShinoPrint_SUB( SubScreen, 2*6, 14*12+6, (u8 *)t_msg[20], 1, 0, 1);
else ShinoPrint_SUB( SubScreen, 2*6, 14*12+6, (u8 *)" ", 1, 0, 1);
} else {
ShinoPrint_SUB( SubScreen, 2*6, 14*12+6, (u8 *)" ", 1, 0, 1);
}
}
} else {
// DrawBox_SUB(SubScreen, 75, 115, 181, 136, 1, 0);
// DrawBox_SUB(SubScreen, 76, 116, 180, 135, 6, 1);
// DrawBox_SUB(SubScreen, 77, 117, 179, 134, 5, 0);
if(r4tf)
if(r4tf) {
ShinoPrint_SUB( SubScreen, 2*6, 14*12+6, (u8 *)t_msg[6], 1, 0, 1);
else
} else {
ShinoPrint_SUB( SubScreen, 2*6, 14*12+6, (u8 *)t_msg[7], 1, 0, 1);
}
// ShinoPrint_SUB( SubScreen, 15*6, 10*12, (u8 *)t_msg[8], 5, 6, 1);
ShinoPrint_SUB( SubScreen, 15*6, 10*12, (u8 *)t_msg[8], 0, 5, 1);
ShinoPrint_SUB( SubScreen, 2*6, 11*12+6, (u8 *)t_msg[9], 1, 0, 1);
@ -654,12 +649,11 @@ void _gba_sel_dsp(int no, int yc, int mod) {
DrawBox_SUB(SubScreen, 8, 82, 247, 109, 5, 0);
if(GBAmode == 0) {
ColorSwap_SUB(SubScreen, 0, 0, 255, 192, 3, 5);
} else {
ColorSwap_SUB(SubScreen, 0, 0, 255, 192, 5, 3);
}
if(GBAmode == 0) {
ColorSwap_SUB(SubScreen, 0, 0, 255, 192, 3, 5);
} else {
ColorSwap_SUB(SubScreen, 0, 0, 255, 192, 5, 3);
}
checkSRAM(filename);
// Unicode2Local(uniname, (u8*)savName, 34);
@ -679,9 +673,7 @@ void _gba_sel_dsp(int no, int yc, int mod) {
st = no - yc;
for(i = 0; i < 15; i++) {
if(i + st < numFiles) {
if(i == yc)
_gba_dsp(i + st, 1, x, y + i);
else _gba_dsp(i + st, 0, x, y + i);
if(i == yc) { _gba_dsp(i + st, 1, x, y + i); } else { _gba_dsp(i + st, 0, x, y + i); }
}
}
}
@ -966,31 +958,14 @@ int gba_sel() {
cmd = -1;
break;
}
if(GBAmode == 0)
ret = writeFileToRam(sortfile[sel]);
else ret = writeFileToNor(sortfile[sel]);
if(GBAmode == 0) { ret = writeFileToRam(sortfile[sel]); } else { ret = writeFileToNor(sortfile[sel]); }
if(ret != 0) {
if(ret == 2) {
err_cnf(9, 10);
} else {
if(GBAmode == 0 && carttype < 3)
err_cnf(7, 8);
else err_cnf(7, 6);
if(GBAmode == 0 && carttype < 3) { err_cnf(7, 8); } else { err_cnf(7, 6); }
}
} else {
/******************
sprintf(tbuf, " %d <%s> ", (int)PatchType[0], SaveVer);
ShinoPrint_SUB( SubScreen, 8*6, 4*12, (u8*)tbuf, 3, 0, 1);
for(i = 0; i < PatchCnt; i++) {
sprintf(tbuf, " %02X %02X %08X ", (int)SaveType, (int)PatchType[i], (int)PatchAddr[i]);
ShinoPrint_SUB( SubScreen, 8*6, (5+i)*12, (u8*)tbuf, 3, 0, 1);
}
inp_key();
****************/
if(GBAmode == 0) {
// SetRompage(384);
gbaMode();
@ -1001,24 +976,13 @@ inp_key();
if(ky & KEY_B) {
if(checkSRAM(filename)) {
// if(cnf_inp(1, 2) & KEY_A) {
if(save_sel(1, filename) >= 0) {
writeSramToFile(filename);
}
if(save_sel(1, filename) >= 0)writeSramToFile(filename);
_gba_sel_dsp(sel, yc, 0);
} else {
err_cnf(4, 5);
}
}
}
/**
while(1) {
swiWaitForVBlank();
scanKeys();
if(keysDown() != repky) break;
}
**/
return(cmd);
}
@ -1044,9 +1008,8 @@ void mainloop(void) {
DrawBox_SUB(SubScreen, 20, 3, 235, 27, 1, 0);
DrawBox_SUB(SubScreen, 21, 4, 234, 26, 5, 1);
DrawBox_SUB(SubScreen, 22, 5, 233, 25, 0, 0);
ShinoPrint_SUB( SubScreen, 9*6, 1*12-2, (u8*)"GBA ExpLoader", 0, 0, 0 );
// ShinoPrint_SUB( SubScreen, 33*6+1, 12, (u8 *)"v0.5ƒÀ", 0, 0, 0 );
ShinoPrint_SUB( SubScreen, 34*6-2, 12, (u8 *)"v0.57", 0, 0, 0 );
ShinoPrint_SUB( SubScreen, 9*6, 1*12-2, (u8*)"GBA ExpLoader", 0, 0, 0);
ShinoPrint_SUB( SubScreen, 34*6-2, 12, (u8 *)VERSTRING, 0, 0, 0);
DrawBox_SUB(SubScreen, 6, 125, 249, 190, 5, 0);
@ -1079,44 +1042,32 @@ REG_EXMEMCNT = (reg & 0xFFE0) | (1 << 4) | (1 << 2) | 1;
ShinoPrint_SUB( SubScreen, 9*6, 5*12, tbuf, 1, 0, 0 );
inp_key();
********/
if(!fatInitDefault()) { err_cnf(0, 1); turn_off(0); }
checkFlashID();
if(carttype == 0 || carttype > 6) {
// if(carttype != 5)
switch (carttype) {
default:
err_cnf(2, 3);
// else err_cnf(9, 10);
turn_off(r4tf);
turn_off(r4tf);
break;
case 0:
err_cnf(2, 3);
turn_off(r4tf);
break;
case 1: ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)" [ 3in1 ]", 0, 0, 0 ); break; // SetRampage(16); // SetShake(0x08);
case 2: ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)"[New3in1]", 0, 0, 0 ); break;
case 3:
SetRompage(0x300);
ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)" [ EZ4 ]", 0, 0, 0 );
break;
case 4: ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)"[EXP256K]", 0, 0, 0 ); break;
case 5: ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)"[EXP128K]", 0, 0, 0 ); break;
case 6: ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)"[ M3/G6 ]", 0, 0, 0 ); break;
}
if(carttype <= 2) {
// SetRampage(16);
// SetShake(0x08);
if(carttype == 1) {
ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)" [ 3in1 ]", 0, 0, 0 );
} else {
ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)"[New3in1]", 0, 0, 0 );
}
}
if(carttype == 3) {
SetRompage(0x300);
ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)" [ EZ4 ]", 0, 0, 0 );
}
if(carttype == 4) {
ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)"[EXP256K]", 0, 0, 0 );
}
if(carttype == 5) {
ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)"[EXP128K]", 0, 0, 0 );
}
if(carttype == 6) {
ShinoPrint_SUB( SubScreen, 23*6, 1*12-2, (u8*)"[ M3/G6 ]", 0, 0, 0 );
}
ShinoPrint_SUB( SubScreen, 9*6, 5*12, (u8 *)t_msg[16], 1, 0, 0 );
if(fatInitDefault() == false) {
err_cnf(0, 1);
turn_off(0);
}
// if(!fatInitDefault()) { err_cnf(0, 1); turn_off(0); }
//ShinoPrint_SUB( SubScreen, 6*6, 6*12, "FAT OK", 1, 0, 0 );
@ -1174,9 +1125,7 @@ inp_key();
GBA_ini();
if(checkSRAM_cnf() == false) {
if(carttype != 5) {
if(cnf_inp(9, 10) & KEY_B)turn_off(r4tf);
}
if(carttype != 5)if(cnf_inp(9, 10) & KEY_B)turn_off(r4tf);
}
@ -1240,23 +1189,18 @@ inp_key();
//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
defaultExceptionHandler();
int i;
vramSetPrimaryBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_SUB_BG, VRAM_D_MAIN_BG);
powerOn(POWER_ALL);
irqInit();
irqSet(IRQ_VBLANK, Vblank);
irqEnable(IRQ_VBLANK);
// FIFOInit();
videoSetMode(MODE_FB0 | DISPLAY_BG2_ACTIVE);
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE );
// SUB_BG0_CR = BG_256_COLOR | BG_MAP_BASE(0) | BG_TILE_BASE(1);
REG_BG0CNT_SUB = BG_256_COLOR | BG_MAP_BASE(0) | BG_TILE_BASE(1);
uint16* map1 = (uint16*)BG_MAP_RAM_SUB(0);
for(i=0;i<(256*192/8/8);i++) map1[i]=i;
for(i=0;i<(256*192/8/8);i++)map1[i]=i;
lcdMainOnTop();
//メイン画面を白で塗りつぶします
ClearBG( MainScreen, RGB15(31,31,31) );
@ -1272,28 +1216,12 @@ int main(void) {
ClearBG_SUB( SubScreen, 0 ); //バックを白に
// videoSetMode(0); //not using the main screen
// videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); //sub bg 0 will be used to print text
// vramSetBankC(VRAM_C_SUB_BG);
// SUB_BG0_CR = BG_MAP_BASE(31);
// BG_PALETTE_SUB[255] = RGB15(31,31,31); //by default font will be rendered with color 255
//consoleInit() is a lot more flexible but this gets you up and running quick
// consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
swiWaitForVBlank();
swiWaitForVBlank();
sysSetBusOwners(BUS_OWNER_ARM9,BUS_OWNER_ARM9);
// iprintf("%s\n%s\n%s\n\n", ROMTITLE, ROMVERSION, ROMDATE);
mainloop();
return 0;
}

View File

@ -3,7 +3,7 @@
#define maindef_h
#define ROMTITLE "GBA ExpLoader"
#define ROMVERSION "Version 0.57 by Rudolph."
#define ROMVERSION "Version 0.58 by Rudolph."
#define ROMDATE ""__DATE__" "__TIME__
#endif

View File

@ -18,8 +18,7 @@
static char *menu_nam;
static char name[32];
bool ret_menu_chk()
{
bool ret_menu_chk() {
FILE *fp;
char buf[5];
@ -38,34 +37,19 @@ bool ret_menu_chk()
menu_nam = NULL;
if(io_dldi_data->ioInterface.ioType == 0x53444353) { // SCDS
menu_nam = "/MSFORSC.NDS";
switch (io_dldi_data->ioInterface.ioType) {
case 0x53444353: menu_nam = "/MSFORSC.NDS"; break; // SCDS
// case 0x4F49524E: menu_nam = "/udisk.nds"; break; // N-Card and Clones
case 0x4E475052: menu_nam = "/akmenu4.nds"; break; // AK.R.P.G NAND
case 0x53475052: menu_nam = "/akmenu4.nds"; break; // AK.R.P.G SD
case 0x44533958: menu_nam = "/loader.nds"; break; // X9 SD
case 0x4F495454: menu_nam = "/TTMENU.DAT"; break; // DSTT
}
// if(_io_dldi == 0x58585858) { // AK+(XXXX)
// menu_nam = "/system/akmenu2_fat.nds";
// }
if(io_dldi_data->ioInterface.ioType == 0x4F49524E) { // N-Card
menu_nam = "/udisk.nds"; // Žbè
}
if(io_dldi_data->ioInterface.ioType == 0x4E475052) { // AK.R.P.G NAND
menu_nam = "/akmenu4.nds";
}
if(io_dldi_data->ioInterface.ioType == 0x53475052) { // AK.R.P.G SD
menu_nam = "/akmenu4.nds";
}
if(io_dldi_data->ioInterface.ioType == 0x44533958) { // X9 SD
menu_nam = "/loader.nds";
}
if(io_dldi_data->ioInterface.ioType == 0x4F495454) { // DSTT
menu_nam = "/TTMENU.DAT";
}
if(menu_nam != NULL) {
fp = fopen(menu_nam, "rb");
if(fp != NULL) {
@ -78,8 +62,7 @@ bool ret_menu_chk()
}
bool ret_menu9_Gen()
{
bool ret_menu9_Gen() {
u32 hed[16];
u8 *ldrBuf;
FILE *ldr;

View File

@ -75,8 +75,7 @@ void _save_list(char *name) {
}
int save_sel(int mod, char *name)
{
int save_sel(int mod, char *name) {
int cmd = 0;
u32 ky, repky;
int i;
@ -128,10 +127,7 @@ int save_sel(int mod, char *name)
ShinoPrint_SUB(SubScreen, x1 + 3, y1 + 20, (u8 *)savnam[0], 2, 3, 1);
for(i = 1; i < 6; i++) {
ShinoPrint_SUB(SubScreen, x1 + 3, y1 + 20 + i*13, (u8 *)savnam[i], 1, 0, 0);
}
for(i = 1; i < 6; i++)ShinoPrint_SUB(SubScreen, x1 + 3, y1 + 20 + i*13, (u8 *)savnam[i], 1, 0, 0);
while(1) {
swiWaitForVBlank();

View File

@ -13,8 +13,10 @@
//東雲フォントデータ用ヘッダ
#include "shinonome_bin.h" //全角ゴシックフォント
#include "shinonomeank_bin.h" //半角フォント
// #include "shinonome_bin.h" //全角ゴシックフォント
// #include "shinonomeank_bin.h" //半角フォント
extern char shinonomeank_bin[];
extern char shinonome_bin[];
#include "tarosa_Graphic.h"
#include "tarosa_Shinofont.h"

View File

@ -3,9 +3,14 @@
#include <ctype.h>
#include "unicode.h"
#include "unicode_u2l_bin.h"
/*#include "unicode_u2l_bin.h"
#include "unicode_l2u_bin.h"
#include "unicode_ank_bin.h"
#include "unicode_ank_bin.h"*/
extern u16 unicode_u2l_bin[];
extern u16 unicode_l2u_bin[];
extern u16 unicode_ank_bin[];
static u16 _codePage = 0;