At least this shows something now...

... still faulty, though.
This commit is contained in:
d0k3 2016-02-25 16:57:01 +01:00
parent c15c559802
commit 6adf9d254d
10 changed files with 194 additions and 408 deletions

View File

@ -9,12 +9,7 @@
#include "font.h" #include "font.h"
#include "draw.h" #include "draw.h"
#include "fs.h" // #include "fs.h"
#ifdef USE_THEME
#include "theme.h"
#endif
static char debugstr[DBG_N_CHARS_X * DBG_N_CHARS_Y] = { 0 };
void ClearScreen(u8* screen, int width, int color) 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) { if (clear_top) {
ClearScreen(TOP_SCREEN0, SCREEN_WIDTH_TOP, STD_COLOR_BG); ClearScreen(TOP_SCREEN0, SCREEN_WIDTH_TOP, color);
ClearScreen(TOP_SCREEN1, SCREEN_WIDTH_TOP, STD_COLOR_BG); ClearScreen(TOP_SCREEN1, SCREEN_WIDTH_TOP, color);
} }
if (clear_bottom) { if (clear_bottom) {
ClearScreen(BOT_SCREEN0, SCREEN_WIDTH_BOT, STD_COLOR_BG); ClearScreen(BOT_SCREEN0, SCREEN_WIDTH_BOT, color);
ClearScreen(BOT_SCREEN1, SCREEN_WIDTH_BOT, STD_COLOR_BG); 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); 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 char str[512] = {}; // 512 should be more than enough
va_list va; 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) { for (char* text = strtok(str, "\n"); text != NULL; text = strtok(NULL, "\n"), y += 10) {
if (use_top) { if (use_top) {
DrawString(TOP_SCREEN0, text, x, y, STD_COLOR_FONT, STD_COLOR_BG); DrawString(TOP_SCREEN0, text, x, y, color, bgcolor);
DrawString(TOP_SCREEN1, text, x, y, STD_COLOR_FONT, STD_COLOR_BG); DrawString(TOP_SCREEN1, text, x, y, color, bgcolor);
} else { } else {
DrawString(BOT_SCREEN0, text, x, y, STD_COLOR_FONT, STD_COLOR_BG); DrawString(BOT_SCREEN0, text, x, y, color, bgcolor);
DrawString(BOT_SCREEN1, text, x, y, STD_COLOR_FONT, STD_COLOR_BG); 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 = (u8*) 0x21000000; // careful, this area is used by other functions in Decrypt9
u8* buffer_t = buffer + (400 * 240 * 3); u8* buffer_t = buffer + (400 * 240 * 3);
@ -125,66 +120,22 @@ void Screenshot(const char* path)
FileWrite(bmp_header, 54, 0); FileWrite(bmp_header, 54, 0);
FileWrite(buffer, 400 * 240 * 3 * 2, 54); FileWrite(buffer, 400 * 240 * 3 * 2, 54);
FileClose(); FileClose();
} }*/
void DebugClear() void ShowError(const char *format, ...)
{ {
memset(debugstr, 0x00, DBG_N_CHARS_X * DBG_N_CHARS_Y); char str[128] = {}; // 128 should be more than enough
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
va_list va; va_list va;
va_start(va, format); va_start(va, format);
vsnprintf(tempstr, 128, format, va); vsnprintf(str, 128, format, va);
va_end(va); va_end(va);
if (adv_output) { ClearScreenFull(true, false, COLOR_BLACK);
memmove(debugstr + DBG_N_CHARS_X, debugstr, DBG_N_CHARS_X * (DBG_N_CHARS_Y - 1)); DrawStringF(true, 80, 80, COLOR_WHITE, COLOR_BLACK, str);
} else {
adv_output = true;
} }
if (*tempstr != '\r') { // not a good way of doing this - improve this later /*void ShowProgress(u64 current, u64 total)
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)
{ {
const u32 progX = SCREEN_WIDTH_TOP - 40; const u32 progX = SCREEN_WIDTH_TOP - 40;
const u32 progY = SCREEN_HEIGHT - 20; 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_SCREEN0, " ", progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG);
DrawString(TOP_SCREEN1, " ", progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG); DrawString(TOP_SCREEN1, " ", progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG);
} }
} }*/
#endif

View File

@ -17,23 +17,6 @@
#define COLOR_WHITE RGB(0xFF, 0xFF, 0xFF) #define COLOR_WHITE RGB(0xFF, 0xFF, 0xFF)
#define COLOR_TRANSPARENT RGB(0xFF, 0x00, 0xEF) // otherwise known as 'super fuchsia' #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 #ifdef EXEC_GATEWAY
#define TOP_SCREEN0 (u8*)(*(u32*)((uint32_t)0x080FFFC0 + 4 * (*(u32*)0x080FFFD8 & 1))) #define TOP_SCREEN0 (u8*)(*(u32*)((uint32_t)0x080FFFC0 + 4 * (*(u32*)0x080FFFD8 & 1)))
#define BOT_SCREEN0 (u8*)(*(u32*)((uint32_t)0x080FFFD0 + 4 * (*(u32*)0x080FFFDC & 1))) #define BOT_SCREEN0 (u8*)(*(u32*)((uint32_t)0x080FFFD0 + 4 * (*(u32*)0x080FFFDC & 1)))
@ -49,15 +32,13 @@
#endif #endif
void ClearScreen(unsigned char *screen, int width, int color); 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 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 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 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); void ShowProgress(u64 current, u64 total);

View File

@ -10,7 +10,7 @@
#include "diskio.h" /* FatFs lower layer API */ #include "diskio.h" /* FatFs lower layer API */
#include "platform.h" #include "platform.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "3dsnand.h" #include "nandio.h"
#define TYPE_SDCARD 0 #define TYPE_SDCARD 0
#define TYPE_SYSNAND 1 #define TYPE_SYSNAND 1
@ -53,6 +53,7 @@ FATpartition DriveInfo[28] = {
{ 0xC00000, TYPE_EMUNAND, P_TWLP } // 27 - EMUNAND3 N3DS TWLP { 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 */ BYTE pdrv /* Physical drive nmuber to identify the drive */
) )
{ {
mode_n3ds = (GetUnitPlatform() == PLATFORM_N3DS);
sdmmc_sdcard_init(); sdmmc_sdcard_init();
return RES_OK; return RES_OK;
} }
@ -96,6 +98,9 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */ UINT count /* Number of sectors to read */
) )
{ {
if ((pdrv >= 4) && mode_n3ds)
pdrv += 12;
if (DriveInfo[pdrv].type == TYPE_SDCARD) { if (DriveInfo[pdrv].type == TYPE_SDCARD) {
if (sdmmc_sdcard_readsectors(sector, count, buff)) { if (sdmmc_sdcard_readsectors(sector, count, buff)) {
return RES_PARERR; return RES_PARERR;
@ -127,6 +132,9 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */ UINT count /* Number of sectors to write */
) )
{ {
if ((pdrv >= 4) && mode_n3ds)
pdrv += 12;
if (DriveInfo[pdrv].type == TYPE_SDCARD) { if (DriveInfo[pdrv].type == TYPE_SDCARD) {
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) { if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
return RES_PARERR; return RES_PARERR;
@ -161,6 +169,9 @@ DRESULT disk_ioctl (
void *buff /* Buffer to send/receive control data */ void *buff /* Buffer to send/receive control data */
) )
{ {
if ((pdrv >= 4) && mode_n3ds)
pdrv += 12;
switch (cmd) { switch (cmd) {
case GET_SECTOR_SIZE: case GET_SECTOR_SIZE:
*((DWORD*) buff) = 0x200; *((DWORD*) buff) = 0x200;

View File

@ -1,6 +1,6 @@
#include "platform.h" #include "platform.h"
#include "fatfs/aes.h" #include "fatfs/aes.h"
#include "fatfs/3dsnand.h" #include "fatfs/nandio.h"
#include "fatfs/sdmmc.h" #include "fatfs/sdmmc.h"
// see: http://3dbrew.org/wiki/Flash_Filesystem // see: http://3dbrew.org/wiki/Flash_Filesystem
@ -20,25 +20,25 @@ static u32 emunand_offset = 0;
u32 CheckEmuNand(void) u32 CheckEmuNand(void)
{ {
u8* buffer = BUFFER_ADDRESS; u8 header[0x200];
u32 nand_size_sectors = getMMCDevice(0)->total_size; u32 nand_size_sectors = getMMCDevice(0)->total_size;
u32 multi_sectors = (GetUnitPlatform() == PLATFORM_3DS) ? EMUNAND_MULTI_OFFSET_O3DS : EMUNAND_MULTI_OFFSET_N3DS; u32 multi_sectors = (GetUnitPlatform() == PLATFORM_3DS) ? EMUNAND_MULTI_OFFSET_O3DS : EMUNAND_MULTI_OFFSET_N3DS;
u32 ret = EMUNAND_NOT_READY; u32 ret = EMUNAND_NOT_READY;
// check the MBR for presence of a hidden partition // check the MBR for presence of a hidden partition
sdmmc_sdcard_readsectors(0, 1, buffer); sdmmc_sdcard_readsectors(0, 1, header);
u32 hidden_sectors = getle32(buffer + 0x1BE + 0x8); u32 hidden_sectors = getle32(header + 0x1BE + 0x8);
for (u32 offset_sector = 0; offset_sector + nand_size_sectors < hidden_sectors; offset_sector += multi_sectors) { for (u32 offset_sector = 0; offset_sector + nand_size_sectors < hidden_sectors; offset_sector += multi_sectors) {
// check for Gateway type EmuNAND // check for Gateway type EmuNAND
sdmmc_sdcard_readsectors(offset_sector + nand_size_sectors, 1, buffer); sdmmc_sdcard_readsectors(offset_sector + nand_size_sectors, 1, header);
if (memcmp(buffer + 0x100, "NCSD", 4) == 0) { if (memcmp(header + 0x100, "NCSD", 4) == 0) {
ret |= EMUNAND_GATEWAY << (2 * (offset_sector / multi_sectors)); ret |= EMUNAND_GATEWAY << (2 * (offset_sector / multi_sectors));
continue; continue;
} }
// check for RedNAND type EmuNAND // check for RedNAND type EmuNAND
sdmmc_sdcard_readsectors(offset_sector + 1, 1, buffer); sdmmc_sdcard_readsectors(offset_sector + 1, 1, header);
if (memcmp(buffer + 0x100, "NCSD", 4) == 0) { if (memcmp(header + 0x100, "NCSD", 4) == 0) {
ret |= EMUNAND_REDNAND << (2 * (offset_sector / multi_sectors)); ret |= EMUNAND_REDNAND << (2 * (offset_sector / multi_sectors));
continue; continue;
} }

View File

@ -1,11 +1,16 @@
#include "fs.h"
#include "draw.h" #include "draw.h"
#include "fs.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#include "fatfs/nandio.h"
static FATFS fs; // don't use this area for anything else!
static FIL file; static FATFS* fs = (FATFS*) 0x20316000;
static DIR dir; // 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() bool InitFS()
{ {
@ -14,213 +19,56 @@ bool InitFS()
*(u32*)0x10000020 = 0; *(u32*)0x10000020 = 0;
*(u32*)0x10000020 = 0x340; *(u32*)0x10000020 = 0x340;
#endif #endif
bool ret = (f_mount(&fs, "0:", 0) == FR_OK); u32 emunand_state = CheckEmuNand();
#ifdef WORK_DIR for (numfs = 0; numfs < 16; numfs++) {
f_chdir(WORK_DIR); char fsname[8];
#endif snprintf(fsname, 7, "%lu:", numfs);
return ret; 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() void DeinitFS()
{ {
LogWrite(NULL); for (u32 i = 0; i < numfs; i++) {
f_mount(NULL, "0:", 1); 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; static const char* drvname[16] = {
if (*path == '/') "sdcard",
path++; "sysctrn", "systwln", "systwlp",
bool ret = (f_open(&file, path, flags) == FR_OK); "emu0ctrn", "emu0twln", "emu0twlp",
#ifdef WORK_DIR "emu1ctrn", "emu1twln", "emu1twlp",
f_chdir("/"); // temporarily change the current directory "emu2ctrn", "emu2twln", "emu2twlp",
if (!ret) ret = (f_open(&file, path, flags) == FR_OK); "emu3ctrn", "emu3twln", "emu3twlp"
f_chdir(WORK_DIR); };
#endif
f_lseek(&file, 0); for (u32 pdrv = 0; (pdrv < numfs) && (pdrv < MAX_ENTRIES); pdrv++) {
f_sync(&file); memset(contents->entry[pdrv].path, 0x00, 16);
return ret; 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) return contents->n_entries;
{
Debug("Opening %s ...", path);
if (!FileOpen(path)) {
Debug("Could not open %s!", path);
return false;
} }
return true; bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fsize, bool recursive)
}
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)
{ {
DIR pdir; DIR pdir;
FILINFO fno; FILINFO fno;
@ -241,13 +89,23 @@ bool GetFileListWorker(char** list, int* lsize, char* fpath, int fsize, bool rec
if (fno.fname[0] == 0) { if (fno.fname[0] == 0) {
ret = true; ret = true;
break; break;
} else if ((inc_files && !(fno.fattrib & AM_DIR)) || (inc_dirs && (fno.fattrib & AM_DIR))) { } else {
snprintf(*list, *lsize, "%s\n", fpath); DirEntry* entry = &(contents->entry[contents->n_entries]);
for(;(*list)[0] != '\0' && (*lsize) > 1; (*list)++, (*lsize)--); snprintf(entry->path, 256, "%s", fpath);
if ((*lsize) <= 1) break; 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 (recursive && (fno.fattrib & AM_DIR)) {
if (!GetFileListWorker(list, lsize, fpath, fsize, recursive, inc_files, inc_dirs)) if (!GetDirContentsWorker(contents, fpath, fsize, recursive))
break; break;
} }
} }
@ -256,53 +114,23 @@ bool GetFileListWorker(char** list, int* lsize, char* fpath, int fsize, bool rec
return ret; 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 char fpath[256]; // 256 is the maximum length of a full path
strncpy(fpath, path, 256); 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) return curdir_contents;
{
#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;
} }
if (!lready) { /*static uint64_t ClustersToBytes(FATFS* fs, DWORD clusters)
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)
{ {
uint64_t sectors = clusters * fs->csize; uint64_t sectors = clusters * fs->csize;
#if _MAX_SS != _MIN_SS #if _MAX_SS != _MIN_SS
@ -326,4 +154,4 @@ uint64_t RemainingStorageSpace()
uint64_t TotalStorageSpace() uint64_t TotalStorageSpace()
{ {
return ClustersToBytes(&fs, fs.n_fatent - 2); return ClustersToBytes(&fs, fs.n_fatent - 2);
} }*/

View File

@ -3,71 +3,35 @@
#include "common.h" #include "common.h"
typedef enum { typedef enum {
T_NAND_BASE, T_NAND_BASE, // might not be needed
T_NONFAT_ROOT, T_NONFAT_ROOT, // might not be needed
T_FAT_ROOT, T_FAT_ROOT,
T_FAT_FILE, T_FAT_FILE,
T_FAT_DIR T_FAT_DIR
} EntryType; } EntryType;
#define MAX_ENTRIES 1024
typedef struct { typedef struct {
char* name; // should point to the correct portion of the path char* name; // should point to the correct portion of the path
char path[256]; char path[256];
u32 size; u32 size;
u32 offset; EntryType type;
EntryType entryType;
} DirEntry; } DirEntry;
typedef struct {
u32 n_entries;
DirEntry entry[MAX_ENTRIES];
} DirStruct;
bool InitFS(); bool InitFS();
void DeinitFS(); void DeinitFS();
/** Opens existing files */ /** Get directory content under a given path **/
bool FileOpen(const char* path); DirStruct* GetDirContents(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);
/** Gets remaining space on SD card in bytes */ /** Gets remaining space on SD card in bytes */
uint64_t RemainingStorageSpace(); uint64_t RemainingStorageSpace();
/** Gets total space on SD card in bytes */ /** Gets total space on SD card in bytes */
uint64_t TotalStorageSpace(); uint64_t TotalStorageSpace();
void FileClose();
void DirClose();

49
source/godmode.c Normal file
View 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
View File

@ -0,0 +1,8 @@
#pragma once
#include "common.h"
#define GODMODE_EXIT_REBOOT 0
#define GODMODE_EXIT_POWEROFF 1
u32 GodMode();

View File

@ -1,4 +1,5 @@
#include "common.h" #include "common.h"
#include "godmode.h"
#include "draw.h" #include "draw.h"
#include "fs.h" #include "fs.h"
#include "i2c.h" #include "i2c.h"
@ -19,12 +20,6 @@ void PowerOff()
int main() int main()
{ {
ClearScreenFull(true, true); (GodMode() == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff();
InitFS();
u32 godmode_exit = 0;
DeinitFS();
(godmode_exit == 0) ? Reboot() : PowerOff();
return 0; return 0;
} }