Add giattributes

This commit is contained in:
Edoardo Lolletti 2025-04-29 18:22:35 +02:00
parent 5f8f69c2ab
commit d01ccfbf47
9 changed files with 1335 additions and 1334 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* text=auto

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,25 @@
#ifndef MAIN_H #ifndef MAIN_H
#define MAIN_H #define MAIN_H
#include <nds.h> #include <nds.h>
#include <fat.h> #include <fat.h>
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern volatile bool programEnd; extern volatile bool programEnd;
extern volatile bool charging; extern volatile bool charging;
extern volatile u8 batteryLevel; extern volatile u8 batteryLevel;
extern PrintConsole topScreen; extern PrintConsole topScreen;
extern PrintConsole bottomScreen; extern PrintConsole bottomScreen;
void clearScreen(PrintConsole* screen); void clearScreen(PrintConsole* screen);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,237 +1,237 @@
#include "menu.h" #include "menu.h"
#include "main.h" #include "main.h"
#define sign(X) ( ((X) > 0) - ((X) < 0) ) #define sign(X) ( ((X) > 0) - ((X) < 0) )
#define repeat(X) for (int _I_ = 0; _I_ < (X); _I_++) #define repeat(X) for (int _I_ = 0; _I_ < (X); _I_++)
Menu* newMenu() Menu* newMenu()
{ {
Menu* m = (Menu*)malloc(sizeof(Menu)); Menu* m = (Menu*)malloc(sizeof(Menu));
m->cursor = 0; m->cursor = 0;
m->page = 0; m->page = 0;
m->itemCount = 0; m->itemCount = 0;
m->nextPage = false; m->nextPage = false;
m->changePage = 0; m->changePage = 0;
m->header[0] = '\0'; m->header[0] = '\0';
for (int i = 0; i < ITEMS_PER_PAGE; i++) for (int i = 0; i < ITEMS_PER_PAGE; i++)
{ {
m->items[i].directory = false; m->items[i].directory = false;
m->items[i].label = NULL; m->items[i].label = NULL;
m->items[i].value = NULL; m->items[i].value = NULL;
} }
return m; return m;
} }
void freeMenu(Menu* m) void freeMenu(Menu* m)
{ {
if (!m) return; if (!m) return;
clearMenu(m); clearMenu(m);
free(m); free(m);
m = NULL; m = NULL;
} }
void addMenuItem(Menu* m, char const* label, char const* value, bool enabled, bool directory) void addMenuItem(Menu* m, char const* label, char const* value, bool enabled, bool directory)
{ {
if (!m) return; if (!m) return;
int i = m->itemCount; int i = m->itemCount;
if (i >= ITEMS_PER_PAGE) return; if (i >= ITEMS_PER_PAGE) return;
m->items[i].directory = directory; m->items[i].directory = directory;
m->items[i].enabled = enabled; m->items[i].enabled = enabled;
if (label) if (label)
{ {
m->items[i].label = (char*)malloc(32); m->items[i].label = (char*)malloc(32);
sprintf(m->items[i].label, "%.31s", label); sprintf(m->items[i].label, "%.31s", label);
} }
if (value) if (value)
{ {
m->items[i].value = (char*)malloc(strlen(value)+1); m->items[i].value = (char*)malloc(strlen(value)+1);
sprintf(m->items[i].value, "%s", value); sprintf(m->items[i].value, "%s", value);
} }
m->itemCount += 1; m->itemCount += 1;
} }
static int alphabeticalCompare(const void* a, const void* b) static int alphabeticalCompare(const void* a, const void* b)
{ {
const Item* itemA = (const Item*)a; const Item* itemA = (const Item*)a;
const Item* itemB = (const Item*)b; const Item* itemB = (const Item*)b;
if (itemA->directory && !itemB->directory) if (itemA->directory && !itemB->directory)
return -1; return -1;
else if (!itemA->directory && itemB->directory) else if (!itemA->directory && itemB->directory)
return 1; return 1;
else else
return strcasecmp(itemA->label, itemB->label); return strcasecmp(itemA->label, itemB->label);
} }
void sortMenuItems(Menu* m) void sortMenuItems(Menu* m)
{ {
qsort(m->items, m->itemCount, sizeof(Item), alphabeticalCompare); qsort(m->items, m->itemCount, sizeof(Item), alphabeticalCompare);
} }
void setMenuHeader(Menu* m, const char* str) void setMenuHeader(Menu* m, const char* str)
{ {
if (!m) return; if (!m) return;
if (!str) if (!str)
{ {
m->header[0] = '\0'; m->header[0] = '\0';
return; return;
} }
const char* strPtr = str; const char* strPtr = str;
if (strlen(strPtr) > 30) if (strlen(strPtr) > 30)
strPtr = str + (strlen(strPtr) - 30); strPtr = str + (strlen(strPtr) - 30);
sprintf(m->header, "%.30s", strPtr); sprintf(m->header, "%.30s", strPtr);
} }
void resetMenu(Menu* m) void resetMenu(Menu* m)
{ {
m->cursor = 0; m->cursor = 0;
m->page = 0; m->page = 0;
m->changePage = 0; m->changePage = 0;
m->nextPage = 0; m->nextPage = 0;
} }
void clearMenu(Menu* m) void clearMenu(Menu* m)
{ {
if (!m) return; if (!m) return;
for (int i = 0; i < ITEMS_PER_PAGE; i++) for (int i = 0; i < ITEMS_PER_PAGE; i++)
{ {
if (m->items[i].label) if (m->items[i].label)
{ {
free(m->items[i].label); free(m->items[i].label);
m->items[i].label = NULL; m->items[i].label = NULL;
} }
if (m->items[i].value) if (m->items[i].value)
{ {
free(m->items[i].value); free(m->items[i].value);
m->items[i].value = NULL; m->items[i].value = NULL;
} }
} }
m->itemCount = 0; m->itemCount = 0;
} }
void printMenu(Menu* m) void printMenu(Menu* m)
{ {
clearScreen(&bottomScreen); clearScreen(&bottomScreen);
if (!m) return; if (!m) return;
//header //header
iprintf("\x1B[42m"); //green iprintf("\x1B[42m"); //green
iprintf("%.30s\n\n", m->header); iprintf("%.30s\n\n", m->header);
iprintf("\x1B[47m"); //white iprintf("\x1B[47m"); //white
if (m->itemCount <= 0) if (m->itemCount <= 0)
{ {
iprintf("Back - [B]\n"); iprintf("Back - [B]\n");
return; return;
} }
//items //items
for (int i = 0; i < m->itemCount; i++) for (int i = 0; i < m->itemCount; i++)
{ {
if (m->items[i].label) if (m->items[i].label)
{ {
if(!m->items[i].enabled) if(!m->items[i].enabled)
iprintf("\x1B[37m"); //gray iprintf("\x1B[37m"); //gray
if (m->items[i].directory) if (m->items[i].directory)
iprintf(" [%.26s]\n", m->items[i].label); iprintf(" [%.26s]\n", m->items[i].label);
else else
iprintf(" %.28s\n", m->items[i].label); iprintf(" %.28s\n", m->items[i].label);
if(!m->items[i].enabled) if(!m->items[i].enabled)
iprintf("\x1B[47m"); //white iprintf("\x1B[47m"); //white
} }
else else
iprintf(" \n"); iprintf(" \n");
} }
//cursor //cursor
iprintf("\x1b[%d;0H>", 2 + m->cursor); iprintf("\x1b[%d;0H>", 2 + m->cursor);
//scroll arrows //scroll arrows
if (m->page > 0) if (m->page > 0)
iprintf("\x1b[2;31H^"); iprintf("\x1b[2;31H^");
if (m->nextPage) if (m->nextPage)
iprintf("\x1b[21;31Hv"); iprintf("\x1b[21;31Hv");
} }
static void _moveCursor(Menu* m, int dir) static void _moveCursor(Menu* m, int dir)
{ {
if (m->changePage != 0) if (m->changePage != 0)
return; return;
m->cursor += sign(dir); m->cursor += sign(dir);
if (m->cursor < 0) if (m->cursor < 0)
{ {
if (m->page <= 0) if (m->page <= 0)
m->cursor = 0; m->cursor = 0;
else else
{ {
m->changePage = -1; m->changePage = -1;
m->cursor = ITEMS_PER_PAGE - 1; m->cursor = ITEMS_PER_PAGE - 1;
} }
} }
else if (m->cursor > m->itemCount-1) else if (m->cursor > m->itemCount-1)
{ {
if (m->nextPage && m->cursor >= ITEMS_PER_PAGE) if (m->nextPage && m->cursor >= ITEMS_PER_PAGE)
{ {
m->changePage = 1; m->changePage = 1;
m->cursor = 0; m->cursor = 0;
} }
else else
{ {
m->cursor = m->itemCount-1; m->cursor = m->itemCount-1;
} }
} }
} }
bool moveCursor(Menu* m) bool moveCursor(Menu* m)
{ {
if (!m) return false; if (!m) return false;
m->changePage = 0; m->changePage = 0;
int lastCursor = m->cursor; int lastCursor = m->cursor;
u32 down = keysDownRepeat(); u32 down = keysDownRepeat();
if (down & KEY_DOWN) if (down & KEY_DOWN)
_moveCursor(m, 1); _moveCursor(m, 1);
else if (down & KEY_UP) else if (down & KEY_UP)
_moveCursor(m, -1); _moveCursor(m, -1);
if (down & KEY_RIGHT) if (down & KEY_RIGHT)
{ {
repeat(10) repeat(10)
_moveCursor(m, 1); _moveCursor(m, 1);
} }
else if (down & KEY_LEFT) else if (down & KEY_LEFT)
{ {
repeat(10) repeat(10)
_moveCursor(m, -1); _moveCursor(m, -1);
} }
return !(lastCursor == m->cursor); return !(lastCursor == m->cursor);
} }

View File

@ -1,46 +1,46 @@
#ifndef MENU_H #ifndef MENU_H
#define MENU_H #define MENU_H
#include <nds/ndstypes.h> #include <nds/ndstypes.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define ITEMS_PER_PAGE 20 #define ITEMS_PER_PAGE 20
typedef struct { typedef struct {
bool directory; bool directory;
bool enabled; bool enabled;
char* label; char* label;
char* value; char* value;
} Item; } Item;
typedef struct { typedef struct {
int cursor; int cursor;
int page; int page;
int itemCount; int itemCount;
bool nextPage; bool nextPage;
int changePage; int changePage;
char header[32]; char header[32];
Item items[ITEMS_PER_PAGE]; Item items[ITEMS_PER_PAGE];
} Menu; } Menu;
Menu* newMenu(); Menu* newMenu();
void freeMenu(Menu* m); void freeMenu(Menu* m);
void addMenuItem(Menu* m, char const* label, char const* value, bool enabled, bool directory); void addMenuItem(Menu* m, char const* label, char const* value, bool enabled, bool directory);
void sortMenuItems(Menu* m); void sortMenuItems(Menu* m);
void setMenuHeader(Menu* m, const char* str); void setMenuHeader(Menu* m, const char* str);
void resetMenu(Menu* m); void resetMenu(Menu* m);
void clearMenu(Menu* m); void clearMenu(Menu* m);
void printMenu(Menu* m); void printMenu(Menu* m);
bool moveCursor(Menu* m); bool moveCursor(Menu* m);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,161 +1,161 @@
#include "message.h" #include "message.h"
#include "main.h" #include "main.h"
void keyWait(u32 key) void keyWait(u32 key)
{ {
while (!programEnd) while (!programEnd)
{ {
swiWaitForVBlank(); swiWaitForVBlank();
scanKeys(); scanKeys();
if (keysDown() & key) if (keysDown() & key)
break; break;
} }
} }
bool choiceBox(const char* message) bool choiceBox(const char* message)
{ {
const int choiceRow = 10; const int choiceRow = 10;
int cursor = 0; int cursor = 0;
clearScreen(&bottomScreen); clearScreen(&bottomScreen);
iprintf("\x1B[33m"); //yellow iprintf("\x1B[33m"); //yellow
iprintf("%s\n", message); iprintf("%s\n", message);
iprintf("\x1B[47m"); //white iprintf("\x1B[47m"); //white
iprintf("\x1b[%d;0H\tYes\n\tNo\n", choiceRow); iprintf("\x1b[%d;0H\tYes\n\tNo\n", choiceRow);
while (!programEnd) while (!programEnd)
{ {
swiWaitForVBlank(); swiWaitForVBlank();
scanKeys(); scanKeys();
//Clear cursor //Clear cursor
iprintf("\x1b[%d;0H ", choiceRow + cursor); iprintf("\x1b[%d;0H ", choiceRow + cursor);
if (keysDown() & (KEY_UP | KEY_DOWN)) if (keysDown() & (KEY_UP | KEY_DOWN))
cursor = !cursor; cursor = !cursor;
//Print cursor //Print cursor
iprintf("\x1b[%d;0H>", choiceRow + cursor); iprintf("\x1b[%d;0H>", choiceRow + cursor);
if (keysDown() & (KEY_A | KEY_START)) if (keysDown() & (KEY_A | KEY_START))
break; break;
if (keysDown() & KEY_B) if (keysDown() & KEY_B)
{ {
cursor = 1; cursor = 1;
break; break;
} }
} }
scanKeys(); scanKeys();
return (cursor == 0)? YES: NO; return (cursor == 0)? YES: NO;
} }
bool choicePrint(const char* message) bool choicePrint(const char* message)
{ {
bool choice = NO; bool choice = NO;
iprintf("\x1B[33m"); //yellow iprintf("\x1B[33m"); //yellow
iprintf("\n%s\n", message); iprintf("\n%s\n", message);
iprintf("\x1B[47m"); //white iprintf("\x1B[47m"); //white
iprintf("Yes - [A]\nNo - [B]\n"); iprintf("Yes - [A]\nNo - [B]\n");
while (!programEnd) while (!programEnd)
{ {
swiWaitForVBlank(); swiWaitForVBlank();
scanKeys(); scanKeys();
if (keysDown() & KEY_A) if (keysDown() & KEY_A)
{ {
choice = YES; choice = YES;
break; break;
} }
else if (keysDown() & KEY_B) else if (keysDown() & KEY_B)
{ {
choice = NO; choice = NO;
break; break;
} }
} }
scanKeys(); scanKeys();
return choice; return choice;
} }
const static u16 keys[] = {KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_LEFT, KEY_A, KEY_B, KEY_X, KEY_Y}; const static u16 keys[] = {KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_LEFT, KEY_A, KEY_B, KEY_X, KEY_Y};
const static char *keysLabels[] = {"\x18", "\x19", "\x1A", "\x1B", "<A>", "<B>", "<X>", "<Y>"}; const static char *keysLabels[] = {"\x18", "\x19", "\x1A", "\x1B", "<A>", "<B>", "<X>", "<Y>"};
bool randomConfirmBox(const char* message) bool randomConfirmBox(const char* message)
{ {
const int choiceRow = 10; const int choiceRow = 10;
int sequencePosition = 0; int sequencePosition = 0;
u8 sequence[8]; u8 sequence[8];
for (int i = 0; i < sizeof(sequence); i++) for (int i = 0; i < sizeof(sequence); i++)
{ {
sequence[i] = rand() % (sizeof(keys) / sizeof(keys[0])); sequence[i] = rand() % (sizeof(keys) / sizeof(keys[0]));
} }
clearScreen(&bottomScreen); clearScreen(&bottomScreen);
iprintf("\x1B[43m"); //yellow iprintf("\x1B[43m"); //yellow
iprintf("%s\n", message); iprintf("%s\n", message);
iprintf("\x1B[47m"); //white iprintf("\x1B[47m"); //white
iprintf("\n<START> cancel\n"); iprintf("\n<START> cancel\n");
while (!programEnd && sequencePosition < sizeof(sequence)) while (!programEnd && sequencePosition < sizeof(sequence))
{ {
swiWaitForVBlank(); swiWaitForVBlank();
scanKeys(); scanKeys();
//Print sequence //Print sequence
iprintf("\x1b[%d;0H", choiceRow); iprintf("\x1b[%d;0H", choiceRow);
for (int i = 0; i < sizeof(sequence); i++) for (int i = 0; i < sizeof(sequence); i++)
{ {
iprintf("\x1B[%0om", i < sequencePosition ? 032 : 047); iprintf("\x1B[%0om", i < sequencePosition ? 032 : 047);
iprintf("%s ", keysLabels[sequence[i]]); iprintf("%s ", keysLabels[sequence[i]]);
} }
if (keysDown() & (KEY_UP | KEY_DOWN | KEY_RIGHT | KEY_LEFT | KEY_A | KEY_B | KEY_X | KEY_Y)) if (keysDown() & (KEY_UP | KEY_DOWN | KEY_RIGHT | KEY_LEFT | KEY_A | KEY_B | KEY_X | KEY_Y))
{ {
if (keysDown() & keys[sequence[sequencePosition]]) if (keysDown() & keys[sequence[sequencePosition]])
sequencePosition++; sequencePosition++;
else else
sequencePosition = 0; sequencePosition = 0;
} }
if (keysDown() & KEY_START) if (keysDown() & KEY_START)
{ {
sequencePosition = 0; sequencePosition = 0;
break; break;
} }
} }
scanKeys(); scanKeys();
return sequencePosition == sizeof(sequence); return sequencePosition == sizeof(sequence);
} }
void messageBox(const char* message) void messageBox(const char* message)
{ {
clearScreen(&bottomScreen); clearScreen(&bottomScreen);
messagePrint(message); messagePrint(message);
} }
void messagePrint(const char* message) void messagePrint(const char* message)
{ {
iprintf("%s\n", message); iprintf("%s\n", message);
iprintf("\nOkay - [A]\n"); iprintf("\nOkay - [A]\n");
while (!programEnd) while (!programEnd)
{ {
swiWaitForVBlank(); swiWaitForVBlank();
scanKeys(); scanKeys();
if (keysDown() & (KEY_A | KEY_B | KEY_START)) if (keysDown() & (KEY_A | KEY_B | KEY_START))
break; break;
} }
scanKeys(); scanKeys();
} }

View File

@ -1,26 +1,26 @@
#ifndef MESSAGE_H #ifndef MESSAGE_H
#define MESSAGE_H #define MESSAGE_H
#include <nds/ndstypes.h> #include <nds/ndstypes.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
enum { enum {
YES = true, YES = true,
NO = false NO = false
}; };
void keyWait(u32 key); void keyWait(u32 key);
bool choiceBox(const char* message); bool choiceBox(const char* message);
bool choicePrint(const char* message); bool choicePrint(const char* message);
bool randomConfirmBox(const char* message); bool randomConfirmBox(const char* message);
void messageBox(const char* message); void messageBox(const char* message);
void messagePrint(const char* message); void messagePrint(const char* message);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,257 +1,257 @@
#include "storage.h" #include "storage.h"
#include "main.h" #include "main.h"
#include "message.h" #include "message.h"
#include <errno.h> #include <errno.h>
#include <nds/sha1.h> #include <nds/sha1.h>
#include <dirent.h> #include <dirent.h>
#define TITLE_LIMIT 39 #define TITLE_LIMIT 39
//progress bar //progress bar
static int lastBars = 0; static int lastBars = 0;
static void printProgressBar(float percent) static void printProgressBar(float percent)
{ {
if (percent < 0.f) percent = 0.f; if (percent < 0.f) percent = 0.f;
if (percent > 1.f) percent = 1.f; if (percent > 1.f) percent = 1.f;
int bars = (int)(30.f * percent); int bars = (int)(30.f * percent);
//skip redundant prints //skip redundant prints
if (bars != lastBars) if (bars != lastBars)
{ {
consoleSelect(&topScreen); consoleSelect(&topScreen);
iprintf("\x1B[42m"); //green iprintf("\x1B[42m"); //green
//Print frame //Print frame
if (lastBars <= 0) if (lastBars <= 0)
{ {
iprintf("\x1b[23;0H["); iprintf("\x1b[23;0H[");
iprintf("\x1b[23;31H]"); iprintf("\x1b[23;31H]");
} }
//Print bars //Print bars
if (bars > 0) if (bars > 0)
{ {
for (int i = 0; i < bars; i++) for (int i = 0; i < bars; i++)
iprintf("\x1b[23;%dH|", 1 + i); iprintf("\x1b[23;%dH|", 1 + i);
} }
lastBars = bars; lastBars = bars;
iprintf("\x1B[47m"); //white iprintf("\x1B[47m"); //white
} }
} }
static void clearProgressBar() static void clearProgressBar()
{ {
lastBars = 0; lastBars = 0;
consoleSelect(&topScreen); consoleSelect(&topScreen);
iprintf("\x1b[23;0H "); iprintf("\x1b[23;0H ");
} }
//files //files
bool fileExists(char const* path) bool fileExists(char const* path)
{ {
return access(path, F_OK) == 0; return access(path, F_OK) == 0;
} }
int copyFile(char const* src, char const* dst) int copyFile(char const* src, char const* dst)
{ {
if (!src) return 1; if (!src) return 1;
unsigned long long size = getFileSizePath(src); unsigned long long size = getFileSizePath(src);
return copyFilePart(src, 0, size, dst); return copyFilePart(src, 0, size, dst);
} }
int copyFilePart(char const* src, u32 offset, u32 size, char const* dst) int copyFilePart(char const* src, u32 offset, u32 size, char const* dst)
{ {
if (!src) return 1; if (!src) return 1;
if (!dst) return 2; if (!dst) return 2;
FILE* fin = fopen(src, "rb"); FILE* fin = fopen(src, "rb");
if (!fin) if (!fin)
{ {
fclose(fin); fclose(fin);
return 3; return 3;
} }
else else
{ {
if (fileExists(dst)) if (fileExists(dst))
remove(dst); remove(dst);
FILE* fout = fopen(dst, "wb"); FILE* fout = fopen(dst, "wb");
if (!fout) if (!fout)
{ {
fclose(fin); fclose(fin);
fclose(fout); fclose(fout);
return 4; return 4;
} }
else else
{ {
fseek(fin, offset, SEEK_SET); fseek(fin, offset, SEEK_SET);
consoleSelect(&topScreen); consoleSelect(&topScreen);
int bytesRead; int bytesRead;
unsigned long long totalBytesRead = 0; unsigned long long totalBytesRead = 0;
#define BUFF_SIZE 128 //Arbitrary. A value too large freezes the ds. #define BUFF_SIZE 128 //Arbitrary. A value too large freezes the ds.
char* buffer = (char*)malloc(BUFF_SIZE); char* buffer = (char*)malloc(BUFF_SIZE);
while (!programEnd) while (!programEnd)
{ {
unsigned int toRead = BUFF_SIZE; unsigned int toRead = BUFF_SIZE;
if (size - totalBytesRead < BUFF_SIZE) if (size - totalBytesRead < BUFF_SIZE)
toRead = size - totalBytesRead; toRead = size - totalBytesRead;
bytesRead = fread(buffer, 1, toRead, fin); bytesRead = fread(buffer, 1, toRead, fin);
fwrite(buffer, bytesRead, 1, fout); fwrite(buffer, bytesRead, 1, fout);
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
printProgressBar( ((float)totalBytesRead / (float)size) ); printProgressBar( ((float)totalBytesRead / (float)size) );
if (bytesRead != BUFF_SIZE) if (bytesRead != BUFF_SIZE)
break; break;
} }
clearProgressBar(); clearProgressBar();
consoleSelect(&bottomScreen); consoleSelect(&bottomScreen);
free(buffer); free(buffer);
} }
fclose(fout); fclose(fout);
} }
fclose(fin); fclose(fin);
return 0; return 0;
} }
unsigned long long getFileSize(FILE* f) unsigned long long getFileSize(FILE* f)
{ {
if (!f) return 0; if (!f) return 0;
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
unsigned long long size = ftell(f); unsigned long long size = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
return size; return size;
} }
unsigned long long getFileSizePath(char const* path) unsigned long long getFileSizePath(char const* path)
{ {
if (!path) return 0; if (!path) return 0;
FILE* f = fopen(path, "rb"); FILE* f = fopen(path, "rb");
unsigned long long size = getFileSize(f); unsigned long long size = getFileSize(f);
fclose(f); fclose(f);
return size; return size;
} }
bool toggleFileReadOnly(const char* path, bool readOnly) bool toggleFileReadOnly(const char* path, bool readOnly)
{ {
int fatAttributes = FAT_getAttr(path); int fatAttributes = FAT_getAttr(path);
if (readOnly) if (readOnly)
fatAttributes |= ATTR_READONLY; fatAttributes |= ATTR_READONLY;
else else
fatAttributes &= ~ATTR_READONLY; fatAttributes &= ~ATTR_READONLY;
return FAT_setAttr(path, fatAttributes) == 0; return FAT_setAttr(path, fatAttributes) == 0;
} }
bool writeToFile(FILE* fd, const char* buffer, size_t size) bool writeToFile(FILE* fd, const char* buffer, size_t size)
{ {
int toWrite = size; int toWrite = size;
size_t written; size_t written;
//write the first 520 bytes as 0, as that's the size of a tmd, but it can be whatever content //write the first 520 bytes as 0, as that's the size of a tmd, but it can be whatever content
while (toWrite > 0 && (written = fwrite(buffer, sizeof(char), toWrite, fd)) > 0) while (toWrite > 0 && (written = fwrite(buffer, sizeof(char), toWrite, fd)) > 0)
{ {
toWrite -= written; toWrite -= written;
buffer += written; buffer += written;
} }
return toWrite == 0; return toWrite == 0;
} }
bool calculateFileSha1(FILE* f, void* digest) bool calculateFileSha1(FILE* f, void* digest)
{ {
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
swiSHA1context_t ctx; swiSHA1context_t ctx;
ctx.sha_block = 0; //this is weird but it has to be done ctx.sha_block = 0; //this is weird but it has to be done
swiSHA1Init(&ctx); swiSHA1Init(&ctx);
char buffer[512]; char buffer[512];
size_t n = 0; size_t n = 0;
while ((n = fread(buffer, sizeof(char), sizeof(buffer), f)) > 0) while ((n = fread(buffer, sizeof(char), sizeof(buffer), f)) > 0)
{ {
swiSHA1Update(&ctx, buffer, n); swiSHA1Update(&ctx, buffer, n);
} }
if (ferror(f) || !feof(f)) if (ferror(f) || !feof(f))
{ {
return false; return false;
} }
swiSHA1Final(digest, &ctx); swiSHA1Final(digest, &ctx);
return true; return true;
} }
bool calculateFileSha1Path(const char* path, void* digest) bool calculateFileSha1Path(const char* path, void* digest)
{ {
FILE* targetFile = fopen(path, "rb"); FILE* targetFile = fopen(path, "rb");
if (!targetFile) if (!targetFile)
{ {
return false; return false;
} }
bool res = calculateFileSha1(targetFile, digest); bool res = calculateFileSha1(targetFile, digest);
fclose(targetFile); fclose(targetFile);
return res; return res;
} }
bool safeCreateDir(const char* path) bool safeCreateDir(const char* path)
{ {
if (((mkdir(path, 0777) == 0) || errno == EEXIST)) if (((mkdir(path, 0777) == 0) || errno == EEXIST))
return true; return true;
char errorStr[512]; char errorStr[512];
sprintf(errorStr, "\x1B[31mError:\x1B[33m Failed to create directory (%s)\n", path); sprintf(errorStr, "\x1B[31mError:\x1B[33m Failed to create directory (%s)\n", path);
messageBox(errorStr); messageBox(errorStr);
return false; return false;
} }
bool removeIfExists(const char* path) bool removeIfExists(const char* path)
{ {
return remove(path) == 0 || errno == ENOENT; return remove(path) == 0 || errno == ENOENT;
} }
// Filesystem type // Filesystem type
typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE;
//trimmed down PARTITION struct from libfat internals //trimmed down PARTITION struct from libfat internals
typedef struct { typedef struct {
const void* disc; const void* disc;
void* cache; void* cache;
// Info about the partition // Info about the partition
FS_TYPE filesysType; FS_TYPE filesysType;
uint64_t totalSize; uint64_t totalSize;
sec_t rootDirStart; sec_t rootDirStart;
uint32_t rootDirCluster; uint32_t rootDirCluster;
uint32_t numberOfSectors; uint32_t numberOfSectors;
sec_t dataStart; sec_t dataStart;
uint32_t bytesPerSector; uint32_t bytesPerSector;
uint32_t sectorsPerCluster; uint32_t sectorsPerCluster;
uint32_t bytesPerCluster; uint32_t bytesPerCluster;
uint32_t fsInfoSector; uint32_t fsInfoSector;
} PARTITION; } PARTITION;
extern PARTITION* _FAT_partition_getPartitionFromPath(const char* path); extern PARTITION* _FAT_partition_getPartitionFromPath(const char* path);
u32 getClusterSizeForPartition(const char* path) u32 getClusterSizeForPartition(const char* path)
{ {
PARTITION* p = _FAT_partition_getPartitionFromPath(path); PARTITION* p = _FAT_partition_getPartitionFromPath(path);
if(!p) if(!p)
return 0; return 0;
return p->bytesPerCluster; return p->bytesPerCluster;
} }

View File

@ -1,34 +1,34 @@
#ifndef STORAGE_H #ifndef STORAGE_H
#define STORAGE_H #define STORAGE_H
#include <nds/ndstypes.h> #include <nds/ndstypes.h>
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
//Files //Files
bool fileExists(char const* path); bool fileExists(char const* path);
int copyFile(char const* src, char const* dst); int copyFile(char const* src, char const* dst);
int copyFilePart(char const* src, u32 offset, u32 size, char const* dst); int copyFilePart(char const* src, u32 offset, u32 size, char const* dst);
unsigned long long getFileSize(FILE* f); unsigned long long getFileSize(FILE* f);
unsigned long long getFileSizePath(char const* path); unsigned long long getFileSizePath(char const* path);
bool toggleFileReadOnly(const char* path, bool readOnly); bool toggleFileReadOnly(const char* path, bool readOnly);
bool writeToFile(FILE* fd, const char* buffer, size_t size); bool writeToFile(FILE* fd, const char* buffer, size_t size);
bool calculateFileSha1(FILE* f, void* digest); bool calculateFileSha1(FILE* f, void* digest);
bool calculateFileSha1Path(const char* path, void* digest); bool calculateFileSha1Path(const char* path, void* digest);
//Directories //Directories
bool safeCreateDir(const char* path); bool safeCreateDir(const char* path);
//Files and directories //Files and directories
bool removeIfExists(const char* path); bool removeIfExists(const char* path);
u32 getClusterSizeForPartition(const char* path); u32 getClusterSizeForPartition(const char* path);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif