Added a extremely basic and buggy file browser.
More documentation and bug fixes.
This commit is contained in:
parent
83a4258bc0
commit
7879ce1597
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "error_codes.h"
|
||||
|
||||
|
||||
|
||||
Result browseFiles(const char *const basePath, char selected[512]);
|
|
@ -34,3 +34,7 @@
|
|||
void LGYFB_init(void);
|
||||
void LGYFB_processFrame(void);
|
||||
void LGYFB_deinit(void);
|
||||
|
||||
#ifndef NDEBUG
|
||||
void LGYFB_dbgDumpFrame(void);
|
||||
#endif
|
||||
|
|
|
@ -15,28 +15,29 @@ enum
|
|||
RES_OK = 0u,
|
||||
RES_SD_CARD_REMOVED = 1u,
|
||||
RES_INVALID_ARG = 2u,
|
||||
RES_OUT_OF_MEM = 3u,
|
||||
|
||||
// fatfs errors.
|
||||
// Caution: Update fs.c on ARM9 if this changes!
|
||||
RES_FR_DISK_ERR = 3u, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||
RES_FR_INT_ERR = 4u, /* (2) Assertion failed */
|
||||
RES_FR_NOT_READY = 5u, /* (3) The physical drive cannot work */
|
||||
RES_FR_NO_FILE = 6u, /* (4) Could not find the file */
|
||||
RES_FR_NO_PATH = 7u, /* (5) Could not find the path */
|
||||
RES_FR_INVALID_NAME = 8u, /* (6) The path name format is invalid */
|
||||
RES_FR_DENIED = 9u, /* (7) Access denied due to prohibited access or directory full */
|
||||
RES_FR_EXIST = 10u, /* (8) Access denied due to prohibited access */
|
||||
RES_FR_INVALID_OBJECT = 11u, /* (9) The file/directory object is invalid */
|
||||
RES_FR_WRITE_PROTECTED = 12u, /* (10) The physical drive is write protected */
|
||||
RES_FR_INVALID_DRIVE = 13u, /* (11) The logical drive number is invalid */
|
||||
RES_FR_NOT_ENABLED = 14u, /* (12) The volume has no work area */
|
||||
RES_FR_NO_FILESYSTEM = 15u, /* (13) There is no valid FAT volume */
|
||||
RES_FR_MKFS_ABORTED = 16u, /* (14) The f_mkfs() aborted due to any problem */
|
||||
RES_FR_TIMEOUT = 17u, /* (15) Could not get a grant to access the volume within defined period */
|
||||
RES_FR_LOCKED = 18u, /* (16) The operation is rejected according to the file sharing policy */
|
||||
RES_FR_NOT_ENOUGH_CORE = 19u, /* (17) LFN working buffer could not be allocated */
|
||||
RES_FR_TOO_MANY_OPEN_FILES = 20u, /* (18) Number of open files > FF_FS_LOCK */
|
||||
RES_FR_INVALID_PARAMETER = 21u, /* (19) Given parameter is invalid */
|
||||
// Caution: Update fres2Res() in fs.c on ARM9 if this changes!
|
||||
RES_FR_DISK_ERR = 4u, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||
RES_FR_INT_ERR = 5u, /* (2) Assertion failed */
|
||||
RES_FR_NOT_READY = 6u, /* (3) The physical drive cannot work */
|
||||
RES_FR_NO_FILE = 7u, /* (4) Could not find the file */
|
||||
RES_FR_NO_PATH = 8u, /* (5) Could not find the path */
|
||||
RES_FR_INVALID_NAME = 9u, /* (6) The path name format is invalid */
|
||||
RES_FR_DENIED = 10u, /* (7) Access denied due to prohibited access or directory full */
|
||||
RES_FR_EXIST = 11u, /* (8) Access denied due to prohibited access */
|
||||
RES_FR_INVALID_OBJECT = 12u, /* (9) The file/directory object is invalid */
|
||||
RES_FR_WRITE_PROTECTED = 13u, /* (10) The physical drive is write protected */
|
||||
RES_FR_INVALID_DRIVE = 14u, /* (11) The logical drive number is invalid */
|
||||
RES_FR_NOT_ENABLED = 15u, /* (12) The volume has no work area */
|
||||
RES_FR_NO_FILESYSTEM = 16u, /* (13) There is no valid FAT volume */
|
||||
RES_FR_MKFS_ABORTED = 17u, /* (14) The f_mkfs() aborted due to any problem */
|
||||
RES_FR_TIMEOUT = 18u, /* (15) Could not get a grant to access the volume within defined period */
|
||||
RES_FR_LOCKED = 19u, /* (16) The operation is rejected according to the file sharing policy */
|
||||
RES_FR_NOT_ENOUGH_CORE = 20u, /* (17) LFN working buffer could not be allocated */
|
||||
RES_FR_TOO_MANY_OPEN_FILES = 21u, /* (18) Number of open files > FF_FS_LOCK */
|
||||
RES_FR_INVALID_PARAMETER = 22u, /* (19) Given parameter is invalid */
|
||||
|
||||
// Custom errors.
|
||||
RES_ROM_TOO_BIG = MAKE_CUSTOM_ERR(0),
|
||||
|
|
|
@ -107,7 +107,7 @@ Result LGY_setGbaRtc(const GbaRtc rtc);
|
|||
Result LGY_getGbaRtc(GbaRtc *const out);
|
||||
Result LGY_backupGbaSave(void);
|
||||
#ifdef ARM11
|
||||
Result LGY_prepareGbaMode(bool biosIntro, const char *const romPath, const char *const savePath);
|
||||
Result LGY_prepareGbaMode(bool biosIntro, char *const romPath);
|
||||
void LGY_switchMode(void);
|
||||
void LGY_handleEvents(void);
|
||||
void LGY_deinit(void);
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "error_codes.h"
|
||||
#include "fs.h"
|
||||
#include "arm11/hardware/hid.h"
|
||||
#include "arm11/fmt.h"
|
||||
#include "hardware/gfx.h"
|
||||
|
||||
|
||||
#define MAX_DIR_ENTRIES (510u)
|
||||
#define DIR_READ_BLOCKS (10u)
|
||||
#define SCREEN_COLS (52u)
|
||||
#define SCREEN_ROWS (24u)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 num;
|
||||
const char *strPtrs[MAX_DIR_ENTRIES];
|
||||
u8 entTypes[MAX_DIR_ENTRIES]; // 0 = file, 1 = dir
|
||||
char strBufs[MAX_DIR_ENTRIES][256];
|
||||
} DirList;
|
||||
|
||||
|
||||
|
||||
// num including null terminator.
|
||||
size_t safeStrcpy(char *const dst, const char *const src, size_t num)
|
||||
{
|
||||
if(num == 0) return 0;
|
||||
|
||||
const size_t len = strlen(src) + 1;
|
||||
if(len > num)
|
||||
{
|
||||
*dst = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(dst, src);
|
||||
return len;
|
||||
}
|
||||
|
||||
static Result scanDir(const char *const path, DirList *const dList)
|
||||
{
|
||||
FILINFO *const fi = (FILINFO*)malloc(DIR_READ_BLOCKS * sizeof(FILINFO));
|
||||
if(fi == NULL) return RES_OUT_OF_MEM;
|
||||
|
||||
memset(dList, 0, sizeof(DirList));
|
||||
|
||||
Result res;
|
||||
DHandle dh;
|
||||
if((res = fOpenDir(&dh, path)) == RES_OK)
|
||||
{
|
||||
u32 read;
|
||||
u32 totalRead = 0;
|
||||
do
|
||||
{
|
||||
if((res = fReadDir(dh, fi, DIR_READ_BLOCKS, &read)) != RES_OK) break;
|
||||
if(totalRead + read > MAX_DIR_ENTRIES) break;
|
||||
|
||||
for(u32 i = 0; i < read; i++)
|
||||
{
|
||||
const u32 dListPos = totalRead + i;
|
||||
dList->strPtrs[dListPos] = dList->strBufs[dListPos];
|
||||
|
||||
// Mark as dir.
|
||||
if(fi[i].fattrib & AM_DIR) dList->entTypes[dListPos] = 1;
|
||||
|
||||
safeStrcpy(dList->strBufs[dListPos], fi[i].fname, 256);
|
||||
}
|
||||
|
||||
totalRead += read;
|
||||
} while(read == DIR_READ_BLOCKS);
|
||||
dList->num = totalRead;
|
||||
|
||||
fCloseDir(dh);
|
||||
}
|
||||
|
||||
free(fi);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void showDirList(const DirList *const dList, u32 start)
|
||||
{
|
||||
// Clear screen.
|
||||
ee_printf("\x1b[2J");
|
||||
|
||||
const u32 listLength = (dList->num - start > SCREEN_ROWS ? start + SCREEN_ROWS : dList->num);
|
||||
for(u32 i = start; i < listLength; i++)
|
||||
{
|
||||
const char *const printStr =
|
||||
(dList->entTypes[i] == 0 ? "\x1b[%lu;H\x1b[37m %.51s" : "\x1b[%lu;H\x1b[33m %.51s");
|
||||
|
||||
ee_printf(printStr, i - start, dList->strPtrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Handle empty dirs.
|
||||
Result browseFiles(const char *const basePath, char selected[512])
|
||||
{
|
||||
if(basePath == NULL || selected == NULL) return RES_INVALID_ARG;
|
||||
|
||||
char *curDir = (char*)malloc(512);
|
||||
if(curDir == NULL) return RES_OUT_OF_MEM;
|
||||
safeStrcpy(curDir, basePath, 512);
|
||||
|
||||
DirList *const dList = (DirList*)malloc(sizeof(DirList));
|
||||
if(dList == NULL) return RES_OUT_OF_MEM;
|
||||
|
||||
Result res;
|
||||
if((res = scanDir(curDir, dList)) != RES_OK) goto end;
|
||||
showDirList(dList, 0);
|
||||
|
||||
s32 cursorPos = 0; // Within the entire list.
|
||||
u32 windowPos = 0; // Window start position within the list.
|
||||
s32 oldCursorPos = 0;
|
||||
while(1)
|
||||
{
|
||||
ee_printf("\x1b[%lu;H ", oldCursorPos - windowPos); // Clear old cursor.
|
||||
ee_printf("\x1b[%lu;H\x1b[37m>", cursorPos - windowPos); // Draw cursor.
|
||||
|
||||
u32 kDown;
|
||||
do
|
||||
{
|
||||
GFX_waitForVBlank0();
|
||||
|
||||
hidScanInput();
|
||||
if(hidGetExtraKeys(0) & KEY_POWER) goto end;
|
||||
kDown = hidKeysDown();
|
||||
} while(kDown == 0);
|
||||
|
||||
oldCursorPos = cursorPos;
|
||||
if(kDown & KEY_DRIGHT) cursorPos += SCREEN_ROWS;
|
||||
if(kDown & KEY_DLEFT) cursorPos -= SCREEN_ROWS;
|
||||
if(kDown & KEY_DUP) cursorPos -= 1;
|
||||
if(kDown & KEY_DDOWN) cursorPos += 1;
|
||||
|
||||
if(cursorPos < 0) cursorPos = dList->num - 1; // Wrap to end of list.
|
||||
if((u32)cursorPos > (dList->num - 1)) cursorPos = 0; // Wrap to start of list.
|
||||
|
||||
if((u32)cursorPos < windowPos)
|
||||
{
|
||||
windowPos = cursorPos;
|
||||
showDirList(dList, windowPos);
|
||||
}
|
||||
if((u32)cursorPos >= windowPos + SCREEN_ROWS)
|
||||
{
|
||||
windowPos = cursorPos - (SCREEN_ROWS - 1);
|
||||
showDirList(dList, windowPos);
|
||||
}
|
||||
|
||||
if(kDown & (KEY_A | KEY_B))
|
||||
{
|
||||
if(kDown & KEY_A)
|
||||
{
|
||||
u32 pathLen = strlen(curDir);
|
||||
// TODO: !!! Insecure !!!
|
||||
if(curDir[pathLen - 1] != '/') curDir[pathLen++] = '/';
|
||||
safeStrcpy(curDir + pathLen, dList->strPtrs[cursorPos], 512);
|
||||
|
||||
if(dList->entTypes[cursorPos] == 0)
|
||||
{
|
||||
safeStrcpy(selected, curDir, 512);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(kDown & KEY_B)
|
||||
{
|
||||
const u32 pathLen = strlen(curDir);
|
||||
if(curDir[pathLen - 2] != ':')
|
||||
{
|
||||
char *tmpPathPtr = curDir + pathLen;
|
||||
while(*--tmpPathPtr != '/');
|
||||
*tmpPathPtr = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if((res = scanDir(curDir, dList)) != RES_OK) break;
|
||||
cursorPos = 0;
|
||||
windowPos = 0;
|
||||
showDirList(dList, 0);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
free(dList);
|
||||
free(curDir);
|
||||
|
||||
// Clear screen.
|
||||
ee_printf("\x1b[2J");
|
||||
|
||||
return res;
|
||||
}
|
|
@ -84,9 +84,10 @@ static u16 checkSaveOverride(u32 gameCode)
|
|||
u16 saveType;
|
||||
} overrideLut[] =
|
||||
{
|
||||
{"\0\0\0\0", SAVE_TYPE_SRAM_256k}, // Homebrew.
|
||||
{"\0\0\0\0", SAVE_TYPE_SRAM_256k}, // Homebrew. TODO: Set WAITCNT to 0x4014?
|
||||
{"GMB\0", SAVE_TYPE_SRAM_256k}, // Goomba Color (Homebrew).
|
||||
{"AA2\0", SAVE_TYPE_EEPROM_64k}, // Super Mario Advance 2.
|
||||
{"A3A\0", SAVE_TYPE_EEPROM_64k}, // Super Mario Advance 3.
|
||||
};
|
||||
|
||||
for(u32 i = 0; i < sizeof(overrideLut) / sizeof(*overrideLut); i++)
|
||||
|
@ -131,7 +132,7 @@ static u16 tryDetectSaveType(u32 romSize)
|
|||
{"EEPROM_V111", SAVE_TYPE_EEPROM_8k}, // Actually EEPROM 4k.
|
||||
{"EEPROM_V120", SAVE_TYPE_EEPROM_8k}, // Confirmed.
|
||||
{"EEPROM_V121", SAVE_TYPE_EEPROM_64k}, // Confirmed.
|
||||
{"EEPROM_V122", SAVE_TYPE_EEPROM_8k}, // Confirmed. Except Super Mario Advance 2.
|
||||
{"EEPROM_V122", SAVE_TYPE_EEPROM_8k}, // Confirmed. Except Super Mario Advance 2/3.
|
||||
{"EEPROM_V124", SAVE_TYPE_EEPROM_64k}, // Confirmed.
|
||||
{"EEPROM_V125", SAVE_TYPE_EEPROM_8k}, // Confirmed.
|
||||
{"EEPROM_V126", SAVE_TYPE_EEPROM_8k}, // Confirmed.
|
||||
|
@ -198,7 +199,7 @@ static void setupFcramForGbaMode(void)
|
|||
while(REG_PDN_FCRAM_CNT & PDN_FCRAM_CNT_CLK_E_ACK); // Wait until clock is disabled.
|
||||
}
|
||||
|
||||
Result LGY_prepareGbaMode(bool biosIntro, const char *const romPath, const char *const savePath)
|
||||
Result LGY_prepareGbaMode(bool biosIntro, char *const romPath)
|
||||
{
|
||||
// Load the ROM image.
|
||||
u32 romSize;
|
||||
|
@ -209,9 +210,12 @@ Result LGY_prepareGbaMode(bool biosIntro, const char *const romPath, const char
|
|||
const u16 saveType = tryDetectSaveType(romSize);
|
||||
|
||||
// Prepare ARM9 for GBA mode + settings and save loading.
|
||||
const u32 romPathLen = strlen(romPath);
|
||||
strcpy(romPath + romPathLen - 4, ".sav");
|
||||
|
||||
u32 cmdBuf[4];
|
||||
cmdBuf[0] = (u32)savePath;
|
||||
cmdBuf[1] = strlen(savePath) + 1;
|
||||
cmdBuf[0] = (u32)romPath;
|
||||
cmdBuf[1] = romPathLen + 1;
|
||||
cmdBuf[2] = biosIntro;
|
||||
cmdBuf[3] = saveType;
|
||||
res = PXI_sendCmd(IPC_CMD9_PREPARE_GBA, cmdBuf, 4);
|
||||
|
@ -256,6 +260,8 @@ void LGY_switchMode(void)
|
|||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include "arm11/hardware/gx.h"
|
||||
#include "arm11/hardware/gpu_regs.h"
|
||||
void debugTests(void)
|
||||
{
|
||||
const u32 kDown = hidKeysDown();
|
||||
|
@ -265,7 +271,20 @@ void debugTests(void)
|
|||
{
|
||||
GbaRtc rtc; LGY_getGbaRtc(&rtc);
|
||||
ee_printf("RTC: %02X.%02X.%04X %02X:%02X:%02X\n", rtc.d, rtc.mon, rtc.y + 0x2000u, rtc.h, rtc.min, rtc.s);
|
||||
|
||||
/*static u8 filter = 1;
|
||||
filter ^= 1;
|
||||
u32 texEnvSource = 0x000F000F;
|
||||
u32 texEnvCombiner = 0x00000000;
|
||||
if(filter == 1)
|
||||
{
|
||||
texEnvSource = 0x00FF00FFu;
|
||||
texEnvCombiner = 0x00010001u;
|
||||
}
|
||||
REG_GX_P3D(GPUREG_TEXENV1_SOURCE) = texEnvSource;
|
||||
REG_GX_P3D(GPUREG_TEXENV1_COMBINER) = texEnvCombiner;*/
|
||||
}
|
||||
if(kDown & KEY_Y) LGYFB_dbgDumpFrame();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -63,13 +63,20 @@ void LGYFB_init(void)
|
|||
REG_LGYFB_TOP_SIZE = LGYFB_SIZE(256u, 160u);
|
||||
REG_LGYFB_TOP_STAT = LGYFB_IRQ_MASK;
|
||||
REG_LGYFB_TOP_IRQ = 0;
|
||||
// With RGB8 output solid red and blue are converted to 0xF8 and green to 0xFA.
|
||||
// So either the hardware uses RGB565 internally or RGB666 with different conversion for green.
|
||||
// Some results:
|
||||
// RGBA8: Same as RGB8 but with useless alpha component.
|
||||
// RGB8: Observed best format. No dithering and best color accuracy (if we ignore the lazy conversion).
|
||||
// RGB565: A little dithering. Good color accuracy.
|
||||
// RGB5551: Lots of dithering. Good color accuracy (a little worse than 565).
|
||||
REG_LGYFB_TOP_ALPHA = 0xFF;
|
||||
REG_LGYFB_TOP_CNT = LGYFB_DMA_E | LGYFB_OUT_SWIZZLE | LGYFB_OUT_FMT_8880 | LGYFB_ENABLE;
|
||||
|
||||
IRQ_registerIsr(IRQ_CDMA_EVENT0, 13, 0, lgyFbDmaIrqHandler);
|
||||
}
|
||||
|
||||
void rotateFrame(void)
|
||||
static void rotateFrame(void)
|
||||
{
|
||||
// With dark filter.
|
||||
alignas(16) static const u8 firstList[1136] =
|
||||
|
@ -122,7 +129,7 @@ alignas(16) static const u8 firstList[1136] =
|
|||
0x18, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x81, 0x00, 0x4F, 0x80, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, // Last 4 bytes: Texture format.
|
||||
0x8E, 0x00, 0x0F, 0x00, 0x01, 0x10, 0x01, 0x00, 0x80, 0x00, 0x0B, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x8B, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x00,
|
||||
|
@ -397,3 +404,13 @@ void LGYFB_deinit(void)
|
|||
|
||||
IRQ_unregisterIsr(IRQ_CDMA_EVENT0);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include "fsutil.h"
|
||||
void LGYFB_dbgDumpFrame(void)
|
||||
{
|
||||
GX_displayTransfer((u32*)0x18200000, 160u<<16 | 256u, (u32*)0x18400000, 160u<<16 | 256u, 1u<<12 | 1u<<8);
|
||||
GFX_waitForEvent(GFX_EVENT_PPF, false);
|
||||
fsQuickWrite((void*)0x18400000, "sdmc:/lgyfb_dbg_frame.bgr", 256 * 160 * 3);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,9 @@ LPFE
|
|||
# LgyFb sometimes (at the end of each scanline?) sends
|
||||
# single requests. Since we can transfer all 8 scanlines
|
||||
# with bursts only we will ignore them.
|
||||
LP 47
|
||||
# LP 31 # RGB5551 and RGB565
|
||||
LP 47 # RGB8
|
||||
# LP 63 # RGBA8
|
||||
LDB
|
||||
STB
|
||||
LPENDB
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "types.h"
|
||||
#include "arm11/hardware/hid.h"
|
||||
#include "arm11/hardware/codec.h"
|
||||
|
@ -25,6 +26,7 @@
|
|||
#include "arm11/power.h"
|
||||
#include "hardware/gfx.h"
|
||||
#include "fs.h"
|
||||
#include "arm11/filebrowser.h"
|
||||
#include "arm.h"
|
||||
|
||||
|
||||
|
@ -35,11 +37,15 @@ int main(void)
|
|||
GFX_setBrightness(DEFAULT_BRIGHTNESS, DEFAULT_BRIGHTNESS);
|
||||
consoleInit(SCREEN_BOT, NULL);
|
||||
//CODEC_init();
|
||||
fMount(FS_DRIVE_SDMC);
|
||||
|
||||
Result res;
|
||||
char *romPath = (char*)malloc(512);
|
||||
*romPath = '\0';
|
||||
if((res = fMount(FS_DRIVE_SDMC)) != RES_OK || (res = browseFiles("sdmc:/", romPath)) != RES_OK || *romPath == '\0')
|
||||
goto end;
|
||||
|
||||
ee_puts("Reading ROM and save...");
|
||||
Result res;
|
||||
if((res = LGY_prepareGbaMode(false, "sdmc:/rom.gba", "sdmc:/rom.sav")) == RES_OK)
|
||||
if((res = LGY_prepareGbaMode(false, romPath)) == RES_OK)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
GFX_setForceBlack(false, true);
|
||||
|
@ -59,7 +65,10 @@ int main(void)
|
|||
__wfi();
|
||||
} while(1);
|
||||
}
|
||||
else printErrorWaitInput(res, 0);
|
||||
|
||||
end:
|
||||
free(romPath);
|
||||
if(res != RES_OK) printErrorWaitInput(res, 0);
|
||||
|
||||
LGY_deinit();
|
||||
fUnmount(FS_DRIVE_SDMC);
|
||||
|
|
|
@ -11,11 +11,11 @@ BEGIN_ASM_FUNC _arm7_stub_start
|
|||
mov r0, #PSR_INT_OFF | PSR_SVC_MODE
|
||||
adr r1, _arm7_stub_start + 0x200 @ 0x3008000
|
||||
msr CPSR_cxsf, r0
|
||||
mov r0, #PSR_INT_OFF | PSR_IRQ_MODE
|
||||
@mov r0, #PSR_INT_OFF | PSR_IRQ_MODE
|
||||
mov sp, r1
|
||||
msr CPSR_cxsf, r0
|
||||
@msr CPSR_cxsf, r0
|
||||
mov r0, #PSR_INT_OFF | PSR_SYS_MODE
|
||||
sub sp, r1, #0x60 @ 0x3007FA0
|
||||
@sub sp, r1, #0x60 @ 0x3007FA0
|
||||
msr CPSR_cxsf, r0
|
||||
mov r3, #0x4700000
|
||||
adr r2, _arm7_stub_16 + 1
|
||||
|
|
|
@ -44,7 +44,7 @@ static struct
|
|||
|
||||
static Result fres2Res(FRESULT fr)
|
||||
{
|
||||
if(fr != FR_OK) return fr + 2;
|
||||
if(fr != FR_OK) return fr + 3;
|
||||
else return RES_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
static u32 g_saveSize = 0;
|
||||
static u32 g_saveHash[8] = {0};
|
||||
static char g_savePath[256] = {0};
|
||||
static char g_savePath[512] = {0};
|
||||
|
||||
|
||||
|
||||
|
@ -82,7 +82,7 @@ Result LGY_prepareGbaMode(bool biosIntro, u16 saveType, const char *const savePa
|
|||
|
||||
setupBiosOverlay(biosIntro);
|
||||
setupSaveType(saveType);
|
||||
strncpy_s(g_savePath, savePath, 255, 256);
|
||||
strncpy_s(g_savePath, savePath, 511, 512);
|
||||
|
||||
Result res = RES_OK;
|
||||
if(g_saveSize != 0)
|
||||
|
|
|
@ -16,6 +16,7 @@ void printError(Result res)
|
|||
"OK",
|
||||
"SD card removed",
|
||||
"Invalid argument",
|
||||
"Out of memory",
|
||||
|
||||
// fatfs errors.
|
||||
"fatfs disk error",
|
||||
|
|
Loading…
Reference in New Issue