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 "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;
}
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);
ClearScreenFull(true, false, COLOR_BLACK);
DrawStringF(true, 80, 80, COLOR_WHITE, COLOR_BLACK, str);
}
#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
}*/

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -1,226 +1,74 @@
#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()
{
#ifndef EXEC_GATEWAY
#ifndef EXEC_GATEWAY
// TODO: Magic?
*(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;
#endif
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;
}
bool DebugFileOpen(const char* path)
{
Debug("Opening %s ...", path);
if (!FileOpen(path)) {
Debug("Could not open %s!", path);
return false;
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;
}
return true;
return contents->n_entries;
}
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)
{
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);
}
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;
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);
if (!GetDirContentsWorker(curdir_contents, fpath, 256, false))
curdir_contents->n_entries = 0;
}
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
return curdir_contents;
}
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);
}
}*/

View File

@ -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
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 "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;
}