mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
At least this shows something now...
... still faulty, though.
This commit is contained in:
parent
c15c559802
commit
6adf9d254d
@ -9,12 +9,7 @@
|
||||
|
||||
#include "font.h"
|
||||
#include "draw.h"
|
||||
#include "fs.h"
|
||||
#ifdef USE_THEME
|
||||
#include "theme.h"
|
||||
#endif
|
||||
|
||||
static char debugstr[DBG_N_CHARS_X * DBG_N_CHARS_Y] = { 0 };
|
||||
// #include "fs.h"
|
||||
|
||||
void ClearScreen(u8* screen, int width, int color)
|
||||
{
|
||||
@ -26,15 +21,15 @@ void ClearScreen(u8* screen, int width, int color)
|
||||
}
|
||||
}
|
||||
|
||||
void ClearScreenFull(bool clear_top, bool clear_bottom)
|
||||
void ClearScreenFull(bool clear_top, bool clear_bottom, int color)
|
||||
{
|
||||
if (clear_top) {
|
||||
ClearScreen(TOP_SCREEN0, SCREEN_WIDTH_TOP, STD_COLOR_BG);
|
||||
ClearScreen(TOP_SCREEN1, SCREEN_WIDTH_TOP, STD_COLOR_BG);
|
||||
ClearScreen(TOP_SCREEN0, SCREEN_WIDTH_TOP, color);
|
||||
ClearScreen(TOP_SCREEN1, SCREEN_WIDTH_TOP, color);
|
||||
}
|
||||
if (clear_bottom) {
|
||||
ClearScreen(BOT_SCREEN0, SCREEN_WIDTH_BOT, STD_COLOR_BG);
|
||||
ClearScreen(BOT_SCREEN1, SCREEN_WIDTH_BOT, STD_COLOR_BG);
|
||||
ClearScreen(BOT_SCREEN0, SCREEN_WIDTH_BOT, color);
|
||||
ClearScreen(BOT_SCREEN1, SCREEN_WIDTH_BOT, color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +62,7 @@ void DrawString(u8* screen, const char *str, int x, int y, int color, int bgcolo
|
||||
DrawCharacter(screen, str[i], x + i * 8, y, color, bgcolor);
|
||||
}
|
||||
|
||||
void DrawStringF(int x, int y, bool use_top, const char *format, ...)
|
||||
void DrawStringF(bool use_top, int x, int y, int color, int bgcolor, const char *format, ...)
|
||||
{
|
||||
char str[512] = {}; // 512 should be more than enough
|
||||
va_list va;
|
||||
@ -78,16 +73,16 @@ void DrawStringF(int x, int y, bool use_top, const char *format, ...)
|
||||
|
||||
for (char* text = strtok(str, "\n"); text != NULL; text = strtok(NULL, "\n"), y += 10) {
|
||||
if (use_top) {
|
||||
DrawString(TOP_SCREEN0, text, x, y, STD_COLOR_FONT, STD_COLOR_BG);
|
||||
DrawString(TOP_SCREEN1, text, x, y, STD_COLOR_FONT, STD_COLOR_BG);
|
||||
DrawString(TOP_SCREEN0, text, x, y, color, bgcolor);
|
||||
DrawString(TOP_SCREEN1, text, x, y, color, bgcolor);
|
||||
} else {
|
||||
DrawString(BOT_SCREEN0, text, x, y, STD_COLOR_FONT, STD_COLOR_BG);
|
||||
DrawString(BOT_SCREEN1, text, x, y, STD_COLOR_FONT, STD_COLOR_BG);
|
||||
DrawString(BOT_SCREEN0, text, x, y, color, bgcolor);
|
||||
DrawString(BOT_SCREEN1, text, x, y, color, bgcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Screenshot(const char* path)
|
||||
/*void Screenshot(const char* path)
|
||||
{
|
||||
u8* buffer = (u8*) 0x21000000; // careful, this area is used by other functions in Decrypt9
|
||||
u8* buffer_t = buffer + (400 * 240 * 3);
|
||||
@ -125,66 +120,22 @@ void Screenshot(const char* path)
|
||||
FileWrite(bmp_header, 54, 0);
|
||||
FileWrite(buffer, 400 * 240 * 3 * 2, 54);
|
||||
FileClose();
|
||||
}
|
||||
}*/
|
||||
|
||||
void DebugClear()
|
||||
void ShowError(const char *format, ...)
|
||||
{
|
||||
memset(debugstr, 0x00, DBG_N_CHARS_X * DBG_N_CHARS_Y);
|
||||
ClearScreen(TOP_SCREEN0, SCREEN_WIDTH_TOP, DBG_COLOR_BG);
|
||||
ClearScreen(TOP_SCREEN1, SCREEN_WIDTH_TOP, DBG_COLOR_BG);
|
||||
#if defined USE_THEME && defined GFX_DEBUG_BG
|
||||
LoadThemeGfx(GFX_DEBUG_BG, true);
|
||||
#endif
|
||||
LogWrite("");
|
||||
LogWrite(NULL);
|
||||
}
|
||||
|
||||
void DebugSet(const char **strs)
|
||||
{
|
||||
if (strs != NULL) for (int y = 0; y < DBG_N_CHARS_Y; y++) {
|
||||
int pos_dbgstr = DBG_N_CHARS_X * (DBG_N_CHARS_Y - 1 - y);
|
||||
snprintf(debugstr + pos_dbgstr, DBG_N_CHARS_X, "%-*.*s", DBG_N_CHARS_X - 1, DBG_N_CHARS_X - 1, strs[y]);
|
||||
}
|
||||
|
||||
int pos_y = DBG_START_Y;
|
||||
for (char* str = debugstr + (DBG_N_CHARS_X * (DBG_N_CHARS_Y - 1)); str >= debugstr; str -= DBG_N_CHARS_X) {
|
||||
if (str[0] != '\0') {
|
||||
DrawString(TOP_SCREEN0, str, DBG_START_X, pos_y, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||
DrawString(TOP_SCREEN1, str, DBG_START_X, pos_y, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||
pos_y += DBG_STEP_Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Debug(const char *format, ...)
|
||||
{
|
||||
static bool adv_output = true;
|
||||
char tempstr[128] = { 0 }; // 128 instead of DBG_N_CHARS_X for log file
|
||||
char str[128] = {}; // 128 should be more than enough
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(tempstr, 128, format, va);
|
||||
vsnprintf(str, 128, format, va);
|
||||
va_end(va);
|
||||
|
||||
if (adv_output) {
|
||||
memmove(debugstr + DBG_N_CHARS_X, debugstr, DBG_N_CHARS_X * (DBG_N_CHARS_Y - 1));
|
||||
} else {
|
||||
adv_output = true;
|
||||
ClearScreenFull(true, false, COLOR_BLACK);
|
||||
DrawStringF(true, 80, 80, COLOR_WHITE, COLOR_BLACK, str);
|
||||
}
|
||||
|
||||
if (*tempstr != '\r') { // not a good way of doing this - improve this later
|
||||
snprintf(debugstr, DBG_N_CHARS_X, "%-*.*s", DBG_N_CHARS_X - 1, DBG_N_CHARS_X - 1, tempstr);
|
||||
LogWrite(tempstr);
|
||||
} else {
|
||||
snprintf(debugstr, DBG_N_CHARS_X, "%-*.*s", DBG_N_CHARS_X - 1, DBG_N_CHARS_X - 1, tempstr + 1);
|
||||
adv_output = false;
|
||||
}
|
||||
|
||||
DebugSet(NULL);
|
||||
}
|
||||
|
||||
#if !defined(USE_THEME) || !defined(ALT_PROGRESS)
|
||||
void ShowProgress(u64 current, u64 total)
|
||||
/*void ShowProgress(u64 current, u64 total)
|
||||
{
|
||||
const u32 progX = SCREEN_WIDTH_TOP - 40;
|
||||
const u32 progY = SCREEN_HEIGHT - 20;
|
||||
@ -198,5 +149,4 @@ void ShowProgress(u64 current, u64 total)
|
||||
DrawString(TOP_SCREEN0, " ", progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||
DrawString(TOP_SCREEN1, " ", progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}*/
|
||||
|
@ -17,23 +17,6 @@
|
||||
#define COLOR_WHITE RGB(0xFF, 0xFF, 0xFF)
|
||||
#define COLOR_TRANSPARENT RGB(0xFF, 0x00, 0xEF) // otherwise known as 'super fuchsia'
|
||||
|
||||
#ifndef USE_THEME
|
||||
#define STD_COLOR_BG COLOR_BLACK
|
||||
#define STD_COLOR_FONT COLOR_WHITE
|
||||
|
||||
#define DBG_COLOR_BG COLOR_BLACK
|
||||
#define DBG_COLOR_FONT COLOR_WHITE
|
||||
|
||||
#define DBG_START_Y 10
|
||||
#define DBG_END_Y (SCREEN_HEIGHT - 10)
|
||||
#define DBG_START_X 10
|
||||
#define DBG_END_X (SCREEN_WIDTH_TOP - 10)
|
||||
#define DBG_STEP_Y 10
|
||||
#endif
|
||||
|
||||
#define DBG_N_CHARS_Y ((DBG_END_Y - DBG_START_Y) / DBG_STEP_Y)
|
||||
#define DBG_N_CHARS_X (((DBG_END_X - DBG_START_X) / 8) + 1)
|
||||
|
||||
#ifdef EXEC_GATEWAY
|
||||
#define TOP_SCREEN0 (u8*)(*(u32*)((uint32_t)0x080FFFC0 + 4 * (*(u32*)0x080FFFD8 & 1)))
|
||||
#define BOT_SCREEN0 (u8*)(*(u32*)((uint32_t)0x080FFFD0 + 4 * (*(u32*)0x080FFFDC & 1)))
|
||||
@ -49,15 +32,13 @@
|
||||
#endif
|
||||
|
||||
void ClearScreen(unsigned char *screen, int width, int color);
|
||||
void ClearScreenFull(bool clear_top, bool clear_bottom);
|
||||
void ClearScreenFull(bool clear_top, bool clear_bottom, int color);
|
||||
|
||||
void DrawCharacter(unsigned char *screen, int character, int x, int y, int color, int bgcolor);
|
||||
void DrawString(unsigned char *screen, const char *str, int x, int y, int color, int bgcolor);
|
||||
void DrawStringF(int x, int y, bool use_top, const char *format, ...);
|
||||
void DrawStringF(bool use_top, int x, int y, int color, int bgcolor, const char *format, ...);
|
||||
|
||||
void Screenshot(const char* path);
|
||||
void DebugClear();
|
||||
void DebugSet(const char **strs);
|
||||
void Debug(const char *format, ...);
|
||||
|
||||
void ShowError(const char *format, ...);
|
||||
void ShowProgress(u64 current, u64 total);
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "diskio.h" /* FatFs lower layer API */
|
||||
#include "platform.h"
|
||||
#include "sdmmc.h"
|
||||
#include "3dsnand.h"
|
||||
#include "nandio.h"
|
||||
|
||||
#define TYPE_SDCARD 0
|
||||
#define TYPE_SYSNAND 1
|
||||
@ -53,6 +53,7 @@ FATpartition DriveInfo[28] = {
|
||||
{ 0xC00000, TYPE_EMUNAND, P_TWLP } // 27 - EMUNAND3 N3DS TWLP
|
||||
};
|
||||
|
||||
static bool mode_n3ds = false;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -78,6 +79,7 @@ DSTATUS disk_initialize (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
mode_n3ds = (GetUnitPlatform() == PLATFORM_N3DS);
|
||||
sdmmc_sdcard_init();
|
||||
return RES_OK;
|
||||
}
|
||||
@ -96,6 +98,9 @@ DRESULT disk_read (
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
if ((pdrv >= 4) && mode_n3ds)
|
||||
pdrv += 12;
|
||||
|
||||
if (DriveInfo[pdrv].type == TYPE_SDCARD) {
|
||||
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
|
||||
return RES_PARERR;
|
||||
@ -127,6 +132,9 @@ DRESULT disk_write (
|
||||
UINT count /* Number of sectors to write */
|
||||
)
|
||||
{
|
||||
if ((pdrv >= 4) && mode_n3ds)
|
||||
pdrv += 12;
|
||||
|
||||
if (DriveInfo[pdrv].type == TYPE_SDCARD) {
|
||||
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
|
||||
return RES_PARERR;
|
||||
@ -161,6 +169,9 @@ DRESULT disk_ioctl (
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
)
|
||||
{
|
||||
if ((pdrv >= 4) && mode_n3ds)
|
||||
pdrv += 12;
|
||||
|
||||
switch (cmd) {
|
||||
case GET_SECTOR_SIZE:
|
||||
*((DWORD*) buff) = 0x200;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "platform.h"
|
||||
#include "fatfs/aes.h"
|
||||
#include "fatfs/3dsnand.h"
|
||||
#include "fatfs/nandio.h"
|
||||
#include "fatfs/sdmmc.h"
|
||||
|
||||
// see: http://3dbrew.org/wiki/Flash_Filesystem
|
||||
@ -20,25 +20,25 @@ static u32 emunand_offset = 0;
|
||||
|
||||
u32 CheckEmuNand(void)
|
||||
{
|
||||
u8* buffer = BUFFER_ADDRESS;
|
||||
u8 header[0x200];
|
||||
u32 nand_size_sectors = getMMCDevice(0)->total_size;
|
||||
u32 multi_sectors = (GetUnitPlatform() == PLATFORM_3DS) ? EMUNAND_MULTI_OFFSET_O3DS : EMUNAND_MULTI_OFFSET_N3DS;
|
||||
u32 ret = EMUNAND_NOT_READY;
|
||||
|
||||
// check the MBR for presence of a hidden partition
|
||||
sdmmc_sdcard_readsectors(0, 1, buffer);
|
||||
u32 hidden_sectors = getle32(buffer + 0x1BE + 0x8);
|
||||
sdmmc_sdcard_readsectors(0, 1, header);
|
||||
u32 hidden_sectors = getle32(header + 0x1BE + 0x8);
|
||||
|
||||
for (u32 offset_sector = 0; offset_sector + nand_size_sectors < hidden_sectors; offset_sector += multi_sectors) {
|
||||
// check for Gateway type EmuNAND
|
||||
sdmmc_sdcard_readsectors(offset_sector + nand_size_sectors, 1, buffer);
|
||||
if (memcmp(buffer + 0x100, "NCSD", 4) == 0) {
|
||||
sdmmc_sdcard_readsectors(offset_sector + nand_size_sectors, 1, header);
|
||||
if (memcmp(header + 0x100, "NCSD", 4) == 0) {
|
||||
ret |= EMUNAND_GATEWAY << (2 * (offset_sector / multi_sectors));
|
||||
continue;
|
||||
}
|
||||
// check for RedNAND type EmuNAND
|
||||
sdmmc_sdcard_readsectors(offset_sector + 1, 1, buffer);
|
||||
if (memcmp(buffer + 0x100, "NCSD", 4) == 0) {
|
||||
sdmmc_sdcard_readsectors(offset_sector + 1, 1, header);
|
||||
if (memcmp(header + 0x100, "NCSD", 4) == 0) {
|
||||
ret |= EMUNAND_REDNAND << (2 * (offset_sector / multi_sectors));
|
||||
continue;
|
||||
}
|
322
source/fs.c
322
source/fs.c
@ -1,11 +1,16 @@
|
||||
#include "fs.h"
|
||||
#include "draw.h"
|
||||
|
||||
#include "fs.h"
|
||||
#include "fatfs/ff.h"
|
||||
#include "fatfs/nandio.h"
|
||||
|
||||
static FATFS fs;
|
||||
static FIL file;
|
||||
static DIR dir;
|
||||
// don't use this area for anything else!
|
||||
static FATFS* fs = (FATFS*) 0x20316000;
|
||||
// reserve one MB for this, just to be safe
|
||||
static DirStruct* curdir_contents = (DirStruct*)0x21000000;
|
||||
// this is the main buffer
|
||||
// static u8* main_buffer = (u8*)0x21100000;
|
||||
// number of currently open file systems
|
||||
static u32 numfs = 0;
|
||||
|
||||
bool InitFS()
|
||||
{
|
||||
@ -14,213 +19,56 @@ bool InitFS()
|
||||
*(u32*)0x10000020 = 0;
|
||||
*(u32*)0x10000020 = 0x340;
|
||||
#endif
|
||||
bool ret = (f_mount(&fs, "0:", 0) == FR_OK);
|
||||
#ifdef WORK_DIR
|
||||
f_chdir(WORK_DIR);
|
||||
#endif
|
||||
return ret;
|
||||
u32 emunand_state = CheckEmuNand();
|
||||
for (numfs = 0; numfs < 16; numfs++) {
|
||||
char fsname[8];
|
||||
snprintf(fsname, 7, "%lu:", numfs);
|
||||
if ((numfs >= 4) && (emunand_state >> (2*((numfs-4)/3)) != EMUNAND_GATEWAY))
|
||||
break;
|
||||
if (f_mount(fs, fsname, 0) != FR_OK) {
|
||||
ShowError("Initialising failed! (%lu/%s)", numfs, fsname);
|
||||
DeinitFS();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeinitFS()
|
||||
{
|
||||
LogWrite(NULL);
|
||||
f_mount(NULL, "0:", 1);
|
||||
for (u32 i = 0; i < numfs; i++) {
|
||||
char fsname[8];
|
||||
snprintf(fsname, 7, "%lu:", numfs);
|
||||
f_mount(NULL, fsname, 1);
|
||||
}
|
||||
numfs = 0;
|
||||
}
|
||||
|
||||
bool FileOpen(const char* path)
|
||||
bool GetRootDirContentsWorker(DirStruct* contents)
|
||||
{
|
||||
unsigned flags = FA_READ | FA_WRITE | FA_OPEN_EXISTING;
|
||||
if (*path == '/')
|
||||
path++;
|
||||
bool ret = (f_open(&file, path, flags) == FR_OK);
|
||||
#ifdef WORK_DIR
|
||||
f_chdir("/"); // temporarily change the current directory
|
||||
if (!ret) ret = (f_open(&file, path, flags) == FR_OK);
|
||||
f_chdir(WORK_DIR);
|
||||
#endif
|
||||
f_lseek(&file, 0);
|
||||
f_sync(&file);
|
||||
return ret;
|
||||
static const char* drvname[16] = {
|
||||
"sdcard",
|
||||
"sysctrn", "systwln", "systwlp",
|
||||
"emu0ctrn", "emu0twln", "emu0twlp",
|
||||
"emu1ctrn", "emu1twln", "emu1twlp",
|
||||
"emu2ctrn", "emu2twln", "emu2twlp",
|
||||
"emu3ctrn", "emu3twln", "emu3twlp"
|
||||
};
|
||||
|
||||
for (u32 pdrv = 0; (pdrv < numfs) && (pdrv < MAX_ENTRIES); pdrv++) {
|
||||
memset(contents->entry[pdrv].path, 0x00, 16);
|
||||
snprintf(contents->entry[pdrv].path + 0, 4, "%lu:", pdrv);
|
||||
snprintf(contents->entry[pdrv].path + 4, 4, "%s", drvname[pdrv]);
|
||||
contents->entry[pdrv].name = contents->entry[pdrv].path + 4;
|
||||
contents->entry[pdrv].size = 0;
|
||||
contents->entry[pdrv].type = T_FAT_ROOT;
|
||||
contents->n_entries = pdrv;
|
||||
}
|
||||
|
||||
bool DebugFileOpen(const char* path)
|
||||
{
|
||||
Debug("Opening %s ...", path);
|
||||
if (!FileOpen(path)) {
|
||||
Debug("Could not open %s!", path);
|
||||
return false;
|
||||
return contents->n_entries;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileCreate(const char* path, bool truncate)
|
||||
{
|
||||
unsigned flags = FA_READ | FA_WRITE;
|
||||
flags |= truncate ? FA_CREATE_ALWAYS : FA_OPEN_ALWAYS;
|
||||
if (*path == '/')
|
||||
path++;
|
||||
bool ret = (f_open(&file, path, flags) == FR_OK);
|
||||
f_lseek(&file, 0);
|
||||
f_sync(&file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DebugFileCreate(const char* path, bool truncate) {
|
||||
Debug("Creating %s ...", path);
|
||||
if (!FileCreate(path, truncate)) {
|
||||
Debug("Could not create %s!", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t FileCopyTo(const char* dest, void* buf, size_t bufsize)
|
||||
{
|
||||
unsigned flags = FA_READ | FA_WRITE | FA_CREATE_ALWAYS;
|
||||
size_t fsize = f_size(&file);
|
||||
size_t result = fsize;
|
||||
FIL dfile;
|
||||
// make sure the containing folder exists
|
||||
char tmp[256] = { 0 };
|
||||
strncpy(tmp, dest, sizeof(tmp) - 1);
|
||||
for (char* p = tmp + 1; *p; p++) {
|
||||
if (*p == '/') {
|
||||
char s = *p;
|
||||
*p = 0;
|
||||
f_mkdir(tmp);
|
||||
*p = s;
|
||||
}
|
||||
}
|
||||
// do the actual copying
|
||||
if (f_open(&dfile, dest, flags) != FR_OK)
|
||||
return 0;
|
||||
f_lseek(&dfile, 0);
|
||||
f_sync(&dfile);
|
||||
f_lseek(&file, 0);
|
||||
f_sync(&file);
|
||||
for (size_t pos = 0; pos < fsize; pos += bufsize) {
|
||||
UINT bytes_read = 0;
|
||||
UINT bytes_written = 0;
|
||||
ShowProgress(pos, fsize);
|
||||
f_read(&file, buf, bufsize, &bytes_read);
|
||||
f_write(&dfile, buf, bytes_read, &bytes_written);
|
||||
if (bytes_read != bytes_written) {
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
ShowProgress(0, 0);
|
||||
f_close(&dfile);
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t FileRead(void* buf, size_t size, size_t foffset)
|
||||
{
|
||||
UINT bytes_read = 0;
|
||||
f_lseek(&file, foffset);
|
||||
f_read(&file, buf, size, &bytes_read);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
bool DebugFileRead(void* buf, size_t size, size_t foffset) {
|
||||
size_t bytesRead = FileRead(buf, size, foffset);
|
||||
if(bytesRead != size) {
|
||||
Debug("ERROR, file is too small!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t FileWrite(void* buf, size_t size, size_t foffset)
|
||||
{
|
||||
UINT bytes_written = 0;
|
||||
f_lseek(&file, foffset);
|
||||
f_write(&file, buf, size, &bytes_written);
|
||||
f_sync(&file);
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
bool DebugFileWrite(void* buf, size_t size, size_t foffset)
|
||||
{
|
||||
size_t bytesWritten = FileWrite(buf, size, foffset);
|
||||
if(bytesWritten != size) {
|
||||
Debug("ERROR, SD card may be full!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t FileGetSize()
|
||||
{
|
||||
return f_size(&file);
|
||||
}
|
||||
|
||||
void FileClose()
|
||||
{
|
||||
f_close(&file);
|
||||
}
|
||||
|
||||
bool DirMake(const char* path)
|
||||
{
|
||||
FRESULT res = f_mkdir(path);
|
||||
bool ret = (res == FR_OK) || (res == FR_EXIST);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DebugDirMake(const char* path)
|
||||
{
|
||||
Debug("Creating dir %s ...", path);
|
||||
if (!DirMake(path)) {
|
||||
Debug("Could not create %s!", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirOpen(const char* path)
|
||||
{
|
||||
return (f_opendir(&dir, path) == FR_OK);
|
||||
}
|
||||
|
||||
bool DebugDirOpen(const char* path)
|
||||
{
|
||||
Debug("Opening %s ...", path);
|
||||
if (!DirOpen(path)) {
|
||||
Debug("Could not open %s!", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirRead(char* fname, int fsize)
|
||||
{
|
||||
FILINFO fno;
|
||||
fno.lfname = fname;
|
||||
fno.lfsize = fsize;
|
||||
bool ret = false;
|
||||
while (f_readdir(&dir, &fno) == FR_OK) {
|
||||
if (fno.fname[0] == 0) break;
|
||||
if ((fno.fname[0] != '.') && !(fno.fattrib & AM_DIR)) {
|
||||
if (fname[0] == 0)
|
||||
strcpy(fname, fno.fname);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DirClose()
|
||||
{
|
||||
f_closedir(&dir);
|
||||
}
|
||||
|
||||
bool GetFileListWorker(char** list, int* lsize, char* fpath, int fsize, bool recursive, bool inc_files, bool inc_dirs)
|
||||
bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fsize, bool recursive)
|
||||
{
|
||||
DIR pdir;
|
||||
FILINFO fno;
|
||||
@ -241,13 +89,23 @@ bool GetFileListWorker(char** list, int* lsize, char* fpath, int fsize, bool rec
|
||||
if (fno.fname[0] == 0) {
|
||||
ret = true;
|
||||
break;
|
||||
} else if ((inc_files && !(fno.fattrib & AM_DIR)) || (inc_dirs && (fno.fattrib & AM_DIR))) {
|
||||
snprintf(*list, *lsize, "%s\n", fpath);
|
||||
for(;(*list)[0] != '\0' && (*lsize) > 1; (*list)++, (*lsize)--);
|
||||
if ((*lsize) <= 1) break;
|
||||
} else {
|
||||
DirEntry* entry = &(contents->entry[contents->n_entries]);
|
||||
snprintf(entry->path, 256, "%s", fpath);
|
||||
entry->name = entry->path + (fpath - fname);
|
||||
if (fno.fattrib & AM_DIR) {
|
||||
entry->type = T_FAT_DIR;
|
||||
entry->size = 0;
|
||||
} else {
|
||||
entry->type = T_FAT_FILE;
|
||||
entry->size = fno.fsize;
|
||||
}
|
||||
contents->n_entries++;
|
||||
if (contents->n_entries >= MAX_ENTRIES)
|
||||
break;
|
||||
}
|
||||
if (recursive && (fno.fattrib & AM_DIR)) {
|
||||
if (!GetFileListWorker(list, lsize, fpath, fsize, recursive, inc_files, inc_dirs))
|
||||
if (!GetDirContentsWorker(contents, fpath, fsize, recursive))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -256,53 +114,23 @@ bool GetFileListWorker(char** list, int* lsize, char* fpath, int fsize, bool rec
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GetFileList(const char* path, char* list, int lsize, bool recursive, bool inc_files, bool inc_dirs)
|
||||
DirStruct* GetDirContents(const char* path)
|
||||
{
|
||||
curdir_contents->n_entries = 0;
|
||||
if (strncmp(path, "", 256) == 0) { // root directory
|
||||
if (!GetRootDirContentsWorker(curdir_contents))
|
||||
curdir_contents->n_entries = 0; // not required, but so what?
|
||||
} else {
|
||||
char fpath[256]; // 256 is the maximum length of a full path
|
||||
strncpy(fpath, path, 256);
|
||||
return GetFileListWorker(&list, &lsize, fpath, 256, recursive, inc_files, inc_dirs);
|
||||
if (!GetDirContentsWorker(curdir_contents, fpath, 256, false))
|
||||
curdir_contents->n_entries = 0;
|
||||
}
|
||||
|
||||
size_t LogWrite(const char* text)
|
||||
{
|
||||
#ifdef LOG_FILE
|
||||
static FIL lfile;
|
||||
static bool lready = false;
|
||||
static size_t lstart = 0;
|
||||
|
||||
if ((text == NULL) && lready) {
|
||||
f_sync(&lfile);
|
||||
f_close(&lfile);
|
||||
lready = false;
|
||||
return lstart; // return the current log start
|
||||
} else if (text == NULL) {
|
||||
return 0;
|
||||
return curdir_contents;
|
||||
}
|
||||
|
||||
if (!lready) {
|
||||
unsigned flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
|
||||
lready = (f_open(&lfile, LOG_FILE, flags) == FR_OK);
|
||||
if (!lready) return 0;
|
||||
lstart = f_size(&lfile);
|
||||
f_lseek(&lfile, lstart);
|
||||
f_sync(&lfile);
|
||||
}
|
||||
|
||||
const char newline = '\n';
|
||||
UINT bytes_written;
|
||||
UINT tlen = strnlen(text, 128);
|
||||
f_write(&lfile, text, tlen, &bytes_written);
|
||||
if (bytes_written != tlen) return 0;
|
||||
f_write(&lfile, &newline, 1, &bytes_written);
|
||||
if (bytes_written != 1) return 0;
|
||||
|
||||
return f_size(&lfile); // return the current position
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint64_t ClustersToBytes(FATFS* fs, DWORD clusters)
|
||||
/*static uint64_t ClustersToBytes(FATFS* fs, DWORD clusters)
|
||||
{
|
||||
uint64_t sectors = clusters * fs->csize;
|
||||
#if _MAX_SS != _MIN_SS
|
||||
@ -326,4 +154,4 @@ uint64_t RemainingStorageSpace()
|
||||
uint64_t TotalStorageSpace()
|
||||
{
|
||||
return ClustersToBytes(&fs, fs.n_fatent - 2);
|
||||
}
|
||||
}*/
|
||||
|
60
source/fs.h
60
source/fs.h
@ -3,71 +3,35 @@
|
||||
#include "common.h"
|
||||
|
||||
typedef enum {
|
||||
T_NAND_BASE,
|
||||
T_NONFAT_ROOT,
|
||||
T_NAND_BASE, // might not be needed
|
||||
T_NONFAT_ROOT, // might not be needed
|
||||
T_FAT_ROOT,
|
||||
T_FAT_FILE,
|
||||
T_FAT_DIR
|
||||
} EntryType;
|
||||
|
||||
#define MAX_ENTRIES 1024
|
||||
|
||||
typedef struct {
|
||||
char* name; // should point to the correct portion of the path
|
||||
char path[256];
|
||||
u32 size;
|
||||
u32 offset;
|
||||
EntryType entryType;
|
||||
EntryType type;
|
||||
} DirEntry;
|
||||
|
||||
typedef struct {
|
||||
u32 n_entries;
|
||||
DirEntry entry[MAX_ENTRIES];
|
||||
} DirStruct;
|
||||
|
||||
bool InitFS();
|
||||
void DeinitFS();
|
||||
|
||||
/** Opens existing files */
|
||||
bool FileOpen(const char* path);
|
||||
bool DebugFileOpen(const char* path);
|
||||
|
||||
/** Opens new files (and creates them if they don't already exist) */
|
||||
bool FileCreate(const char* path, bool truncate);
|
||||
bool DebugFileCreate(const char* path, bool truncate);
|
||||
|
||||
/** Copies currently opened file to destination (must provide buffer) */
|
||||
size_t FileCopyTo(const char* dest, void* buf, size_t bufsize);
|
||||
|
||||
/** Reads contents of the opened file */
|
||||
size_t FileRead(void* buf, size_t size, size_t foffset);
|
||||
bool DebugFileRead(void* buf, size_t size, size_t foffset);
|
||||
|
||||
/** Writes to the opened file */
|
||||
size_t FileWrite(void* buf, size_t size, size_t foffset);
|
||||
bool DebugFileWrite(void* buf, size_t size, size_t foffset);
|
||||
|
||||
/** Gets the size of the opened file */
|
||||
size_t FileGetSize();
|
||||
|
||||
/** Creates a directory */
|
||||
bool DirMake(const char* path);
|
||||
bool DebugDirMake(const char* path);
|
||||
|
||||
/** Opens an existing directory */
|
||||
bool DirOpen(const char* path);
|
||||
bool DebugDirOpen(const char* path);
|
||||
|
||||
/** Reads next file name to fname from opened directory,
|
||||
returns false if all files in directory are processed.
|
||||
fname needs to be allocated to fsize bytes minimum. */
|
||||
bool DirRead(char* fname, int fsize);
|
||||
|
||||
/** Get list of files under a given path **/
|
||||
bool GetFileList(const char* path, char* list, int lsize, bool recursive, bool inc_files, bool inc_dirs);
|
||||
|
||||
/** Writes text to a constantly open log file **/
|
||||
size_t LogWrite(const char* text);
|
||||
/** Get directory content under a given path **/
|
||||
DirStruct* GetDirContents(const char* path);
|
||||
|
||||
/** Gets remaining space on SD card in bytes */
|
||||
uint64_t RemainingStorageSpace();
|
||||
|
||||
/** Gets total space on SD card in bytes */
|
||||
uint64_t TotalStorageSpace();
|
||||
|
||||
void FileClose();
|
||||
|
||||
void DirClose();
|
||||
|
49
source/godmode.c
Normal file
49
source/godmode.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include "godmode.h"
|
||||
#include "draw.h"
|
||||
#include "hid.h"
|
||||
#include "fs.h"
|
||||
|
||||
void DrawDirContents(DirStruct* contents, u32 offset, u32 cursor) {
|
||||
const int str_width = 38;
|
||||
const u32 stp_y = 10;
|
||||
const u32 pos_x = 10;
|
||||
u32 pos_y = 10;
|
||||
|
||||
for (u32 i = 0; pos_y < SCREEN_HEIGHT; i++) {
|
||||
char tempstr[str_width + 1];
|
||||
u32 offset_i = offset + i;
|
||||
u32 color_font;
|
||||
u32 color_bg;
|
||||
if (offset_i < contents->n_entries) {
|
||||
color_font = COLOR_WHITE;
|
||||
color_bg = COLOR_BLACK;
|
||||
snprintf(tempstr, str_width + 1, "%-*.*s", str_width, str_width, contents->entry[offset_i].name);
|
||||
} else {
|
||||
color_font = COLOR_BLACK;
|
||||
color_bg = COLOR_WHITE;
|
||||
snprintf(tempstr, str_width + 1, "%-*.*s", str_width, str_width, "");
|
||||
}
|
||||
DrawStringF(false, pos_x, pos_y, color_font, color_bg, tempstr);
|
||||
pos_y += stp_y;
|
||||
}
|
||||
}
|
||||
|
||||
u32 GodMode() {
|
||||
u32 exit_mode = GODMODE_EXIT_REBOOT;
|
||||
DirStruct* contents;
|
||||
|
||||
ClearScreenFull(true, true, COLOR_BLACK);
|
||||
if (!InitFS()) {
|
||||
// ShowError("Could not initialize fs!");
|
||||
InputWait();
|
||||
return exit_mode;
|
||||
}
|
||||
|
||||
contents = GetDirContents("");
|
||||
DrawDirContents(contents, 0, 0);
|
||||
InputWait();
|
||||
|
||||
DeinitFS();
|
||||
|
||||
return exit_mode;
|
||||
}
|
8
source/godmode.h
Normal file
8
source/godmode.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define GODMODE_EXIT_REBOOT 0
|
||||
#define GODMODE_EXIT_POWEROFF 1
|
||||
|
||||
u32 GodMode();
|
@ -1,4 +1,5 @@
|
||||
#include "common.h"
|
||||
#include "godmode.h"
|
||||
#include "draw.h"
|
||||
#include "fs.h"
|
||||
#include "i2c.h"
|
||||
@ -19,12 +20,6 @@ void PowerOff()
|
||||
|
||||
int main()
|
||||
{
|
||||
ClearScreenFull(true, true);
|
||||
InitFS();
|
||||
|
||||
u32 godmode_exit = 0;
|
||||
|
||||
DeinitFS();
|
||||
(godmode_exit == 0) ? Reboot() : PowerOff();
|
||||
(GodMode() == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user