Fixed FAT formatting and improved UI

This commit is contained in:
Lillian Skinner 2024-11-13 17:08:22 -05:00
parent b09e376e67
commit e6c617fea5
No known key found for this signature in database
18 changed files with 483 additions and 197 deletions

View File

@ -15,7 +15,8 @@ on:
jobs:
build:
runs-on: ubuntu-latest
container: devkitpro/devkitarm
# Something something old releases being hostile and damaging, boo hoo dkp. Maybe don't make extremely breaking changes.
container: devkitpro/devkitarm:20241104
name: Build with Docker using devkitARM
steps:
- name: Checkout repo

View File

@ -13,6 +13,7 @@ GIT_VER := $(shell git tag -l --points-at HEAD)
else
GIT_VER := $(shell git describe --abbrev=0 --tags)-$(shell git rev-parse --short=7 HEAD)
endif
BUILD_DATE := $(shell date +'%Y%m%d')
# Ensure version.h exists
ifeq (,$(wildcard include/version.h))
@ -27,7 +28,7 @@ endif
# Print new version if changed
ifeq (,$(findstring $(GIT_VER), $(shell cat include/version.h)))
$(shell echo -n $(GIT_VER) > ../../nitrofiles/version_twlnandtool)
$(shell printf "#ifndef VERSION_H\n#define VERSION_H\n\n#define VERSION \"$(GIT_VER)\"\n\n#endif // VERSION_H\n" > include/version.h)
$(shell printf "#ifndef VERSION_H\n#define VERSION_H\n\n#define VERSION \"$(GIT_VER)\"\n#define BUILD_DATE \"$(BUILD_DATE)\"\n\n#endif // VERSION_H\n" > include/version.h)
endif
#---------------------------------------------------------------------------------
@ -41,8 +42,7 @@ BUILD := build
SOURCES := src src/nand src/nand/polarssl src/nand/twltool
INCLUDES := include src/nand
DATA := ../data
GRAPHICS := ../gfx
GRAPHICS := fonts
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
@ -81,11 +81,14 @@ export ARM9ELF := $(CURDIR)/$(TARGET).elf
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BMPFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.bmp)))
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
@ -105,7 +108,9 @@ endif
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(BMPFILES:.bmp=.o) \
$(PNGFILES:.png=.o) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) \
export HFILES := $(BMPFILES:.bmp=.h) $(PNGFILES:.png=.h) $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
@ -139,7 +144,7 @@ $(ARM9ELF) : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
@ -155,7 +160,7 @@ $(ARM9ELF) : $(OFILES)
grit $< -fts -o$*
#---------------------------------------------------------------------------------
%.s %.h : %.png %.grit
%.s %.h : %.png %.grit
#---------------------------------------------------------------------------------
grit $< -fts -o$*

BIN
arm9/fonts/font.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

25
arm9/fonts/font.grit Normal file
View File

@ -0,0 +1,25 @@
#-------------------------------------------------------
# graphics in tile format
#-------------------------------------------------------
-gt
#-------------------------------------------------------
# output first 16 colors of the palette
#-------------------------------------------------------
-pw16
#-------------------------------------------------------
# no tile reduction
#-------------------------------------------------------
-mR!
#-------------------------------------------------------
# no map output
#-------------------------------------------------------
-m!
#-------------------------------------------------------
# graphics bit depth is 4 (16 color)
#-------------------------------------------------------
-gB4

View File

@ -10,14 +10,14 @@
#include "nand/nandfirm.h"
#include "video.h"
#include "nitrofs.h"
#include "font.h"
#include <stdlib.h>
#include <stdio.h>
/*
TODO:
- Write good NAND I/O routine
- Import NandFirm
- Write good NAND read routine
- Detect debugger vs dev
- Create FAT
@ -35,7 +35,7 @@
};
Pad to 0x200b and make sure to have 0x55AA (CRINGE I HATE MBR I HATE MBR I HATE MBR) <-- I don't even remember writing this.
Now fill 0x200*688b (total 0x171000) afterwards with zerobytes.
Now fill 0x200*B88b (total 0x171000) afterwards with zerobytes.
Congrats. This is a formatted file system. Please don't hurt me.
@ -74,6 +74,7 @@ u8 batteryLevel = 0;
u8 region = 0;
u32 consoleSign;
char consoleSignName[9];
char consoleType[9];
PrintConsole topScreen;
PrintConsole bottomScreen;
@ -81,34 +82,34 @@ PrintConsole bottomScreen;
typedef enum {
MENUSTATE_FS_MENU,
MENUSTATE_NF_MENU,
MENUSTATE_NULL,
MENUSTATE_TEST,
MENUSTATE_TEST2,
MENUSTATE_EXIT
} MenuState;
static int _mainMenu(int cursor)
{
//top screen
clearScreen(cMAIN);
printf("\n\x1B[40mTwlNandTool Ver%s", VERSION);
printf("\nRun on: %s (%02lX)", consoleSignName, consoleSign);
printf("\n\nNAND repair tool by RMC/RVTR");
printf("\n\nMode: Main Menu");
clearScreen(cSUB);
clearScreen(cMAIN);
//menu
Menu* m = newMenu();
setMenuHeader(m, "TwlNandTool");
setListHeader(m, "START MENU");
char modeStr[32];
addMenuItem(m, "FileSystem Menu", NULL, 0);
addMenuItem(m, "NandFirm menu", NULL, 0);
addMenuItem(m, "Debug1", NULL, 0);
addMenuItem(m, "Exit", NULL, 0);
addMenuItem(m, "FileSystem Menu", NULL, 0, "Options such as repairing MBR\n and formatting twl_main/photo.");
addMenuItem(m, "NandFirm menu", NULL, 0, "NandFirm (stage2) installers\n and version testing.");
addMenuItem(m, "---------------", NULL, 0, "");
addMenuItem(m, "Debug1", NULL, 0, "Testing area");
addMenuItem(m, "Debug2", NULL, 0, "Testing area");
addMenuItem(m, "Exit", NULL, 0, "Leave the program.");
m->cursor = cursor;
m->cursor = (cursor);
//bottom screen
printMenu(m);
printMenu(m, 0);
while (!programEnd)
{
@ -116,7 +117,7 @@ static int _mainMenu(int cursor)
scanKeys();
if (moveCursor(m))
printMenu(m);
printMenu(m, 0);
if (keysDown() & KEY_A)
break;
@ -155,8 +156,22 @@ int main(int argc, char **argv)
strcpy(consoleSignName, "dev");
}
if (consoleSign == 0x00) {
strcpy(consoleType, "Retail");
} else if (consoleSign == 0x02) {
strcpy(consoleType, "Panda");
}/*
Do some check here to determine retail, panda, and debugger.
Then block debuggers due to different FW and a higher chance of messing stuff up without an easy fix.
else if (consoleSign == 0x02 || ) {
strcpy consoleType, "Debugger"
}
*/
videoInit();
srand(time(0));
keysSetRepeat(25, 5);
//_setupScreens();
@ -172,7 +187,7 @@ int main(int argc, char **argv)
//setup sd card access
if (!fatInitDefault()) {
messageBox("fatInitDefault()...\x1B[31mFailed\n\x1B[40m\n\nSome features will not work.");
messageBox("fatInitDefault()...\x1B[31mFailed\n\x1B[30m\n\nSome features will not work.");
//return 0;
}
@ -189,7 +204,7 @@ int main(int argc, char **argv)
if (keysDown() & KEY_SELECT )
break;
}
messageBox("nitroFSInit()...\x1B[31mFailed\n\x1B[40m\nSome features will not work.\n\nTry placing the SRL for your DSion your SD card root like this:\n\nSDMC:/TwlNandTool.prod.srl\nSDMC:/TwlNandTool.dev.srl\nSDMC:/ntrboot.nds\n");
messageBox("nitroFSInit()...\x1B[31mFailed\n\x1B[30m\nSome features will not work.\n\nTry placing the SRL for your DSion your SD card root like this:\n\nSDMC:/TwlNandTool.prod.srl\nSDMC:/TwlNandTool.dev.srl\nSDMC:/ntrboot.nds\n");
}
}
}
@ -197,9 +212,12 @@ int main(int argc, char **argv)
//setup nand access
if (!fatMountSimple("nand", &io_dsi_nand)) {
messageBox("nand init \x1B[31mfailed\n\x1B[40m\n\nNAND must be repaired.");
messageBox("nand init \x1B[31mfailed\n\x1B[30m\n\nNAND must be repaired.");
}
clearScreen(cSUB);
clearScreen(cMAIN);
int cursor = 0;
while (!programEnd)
@ -217,10 +235,17 @@ int main(int argc, char **argv)
nfMain();
break;
case MENUSTATE_NULL:
break;
case MENUSTATE_TEST:
debug1();
break;
case MENUSTATE_TEST2:
debug2();
break;
case MENUSTATE_EXIT:
programEnd = true;
break;
@ -246,23 +271,73 @@ int debug1(void) {
clearScreen(cSUB);
iprintf("\n>> Debug1");
iprintf("\n NandFirm write ");
iprintf("\n Show font ");
iprintf("\n--------------------------------");
printf("Opening NandFirm...\n");
FILE *file = fopen("nitro:/import/prod/menu-launcher.nand", "r");
if(file) {
// First 0x200 of NandFirm is reserved for MBR
fseek(file, 0, SEEK_END);
int file_length = ftell(file);
fseek(file, 0x200, SEEK_SET);
printf("Importing...\n");
good_nandio_write_file(0x200, file_length - ftell(file), file, false);
printf("Done!\n");
fclose(file);
for (int i = 0; i <= 200; i++) {
printf("%c ", (char)i);
}
iprintf("\n\n Please Push Select To Return ");
while (true)
{
swiWaitForVBlank();
scanKeys();
if (keysDown() & KEY_SELECT )
break;
}
}
int debug2(void) {
clearScreen(cSUB);
iprintf("\n>> Debug1");
iprintf("\n Stupid AES-CTR BS ");
iprintf("\n--------------------------------");
nand_ReadSectors(877, 1, sector_buf);
dsi_nand_crypt(sector_buf, sector_buf, 877, SECTOR_SIZE / AES_BLOCK_SIZE);
printf("\n ");
for (int i = 452; i < SECTOR_SIZE; i++) {
printf("%02X", sector_buf[i]);
if ((i + 1) % 2 == 0) {
printf(" ");
}
if ((i - 443) % 8 == 0 && i != 444) {
printf("\n ");
}
}
iprintf("\n\n Read in");
while (true)
{
swiWaitForVBlank();
scanKeys();
if (keysDown() & KEY_SELECT )
break;
}
dsi_nand_crypt(sector_buf, sector_buf, 877, SECTOR_SIZE / AES_BLOCK_SIZE);
printf("\n ");
for (int i = 444; i < SECTOR_SIZE; i++) {
printf("%02X", sector_buf[i]);
if ((i + 1) % 2 == 0) {
printf(" ");
}
if ((i - 443) % 8 == 0 && i != 444) {
printf("\n ");
}
}
iprintf("\n\n Read out");
while (true)
{
swiWaitForVBlank();

View File

@ -19,12 +19,14 @@ extern u8 batteryLevel;
extern u8 region;
extern u32 consoleSign;
extern char consoleSignName[9];
extern char consoleType[9];
void installMenu();
void titleMenu();
void backupMenu();
void testMenu();
int debug1();
int debug2();
extern PrintConsole topScreen;
extern PrintConsole bottomScreen;

View File

@ -1,6 +1,8 @@
#include "menu.h"
#include "main.h"
#include "video.h"
#include "version.h"
#include "nand/nandio.h"
Menu* newMenu()
{
@ -12,12 +14,14 @@ Menu* newMenu()
m->nextPage = false;
m->changePage = 0;
m->header[0] = '\0';
m->lheader[0] = '\0';
for (int i = 0; i < ITEMS_PER_PAGE; i++)
{
m->items[i].directory = false;
m->items[i].label = NULL;
m->items[i].value = NULL;
m->items[i].help = NULL;
}
return m;
@ -33,7 +37,7 @@ void freeMenu(Menu* m)
m = NULL;
}
void addMenuItem(Menu* m, char const* label, char const* value, bool directory)
void addMenuItem(Menu* m, char const* label, char const* value, bool directory, char const* help)
{
if (!m) return;
@ -54,6 +58,12 @@ void addMenuItem(Menu* m, char const* label, char const* value, bool directory)
sprintf(m->items[i].value, "%s", value);
}
if (help)
{
m->items[i].help = (char*)malloc(200);
sprintf(m->items[i].help, "%s", help);
}
m->itemCount += 1;
}
@ -93,6 +103,25 @@ void setMenuHeader(Menu* m, char* str)
sprintf(m->header, "%.30s", strPtr);
}
void setListHeader(Menu* m, char* str)
{
if (!m) return;
if (!str)
{
m->lheader[0] = '\0';
return;
}
char* strPtr = str;
if (strlen(strPtr) > 30)
strPtr = str + (strlen(strPtr) - 30);
sprintf(m->lheader, "%.30s", strPtr);
}
void resetMenu(Menu* m)
{
m->cursor = 0;
@ -123,39 +152,122 @@ void clearMenu(Menu* m)
m->itemCount = 0;
}
void printMenu(Menu* m)
void clearHelpMenu(Menu* m)
{
clearScreen(cSUB);
consoleSet(cMAIN);
iprintf("\x1B[40m\x1b[0;0H\x1B[40m%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%cHelp%c%c%c%c%c", (char)138, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)134, (char)135, (char)136, (char)136, (char)136, (char)140);
iprintf("\x1b[1;0H\x1b[K");
iprintf("\x1b[2;0H\x1b[K");
iprintf("\x1b[3;0H\x1b[K");
iprintf("\x1b[4;0H\x1b[K");
iprintf("\x1b[5;0H\x1b[K");
iprintf("\x1b[6;0H\x1b[K");
iprintf("\x1b[7;0H\x1b[K");
iprintf("\x1b[8;0H\x1b[K");
iprintf("\x1b[9;0H%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", (char)139, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)141);
iprintf("\x1b[10;0H\x1b[K");
iprintf("\x1b[11;0H\x1B[40m%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%cInfo%c%c%c%c%c", (char)138, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)134, (char)135, (char)136, (char)136, (char)136, (char)140);
iprintf("\x1B[30m\x1b[12;0H\x1b[K %s %s", m->header, VERSION);
iprintf("\x1b[13;0H\x1b[K Built on: %s", BUILD_DATE);
iprintf("\x1b[14;0H\x1b[K Made by: RMC/RVTR");
iprintf("\x1b[15;0H\x1b[K");
iprintf("\x1b[16;0H\x1b[K");
iprintf("\x1b[17;0H\x1b[K Run on: %s\x1B[40m", consoleType);
iprintf("\x1b[18;0H%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\x1B[30m", (char)139, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)136, (char)141);
}
void printHelpMenu(Menu* m)
{
if (!m) return;
iprintf("\x1B[30m\x1b[1;0H %s", m->items[m->cursor].help);
}
void printMenu(Menu* m, int level)
{
clearHelpMenu(m);
printHelpMenu(m);
consoleSet(cSUB);
if (!m) return;
//header
iprintf("\x1B[42m"); //green
iprintf("%.30s\n\n", m->header);
iprintf("\x1B[40m"); //white
if (m->itemCount <= 0)
{
iprintf("Back - [B]\n");
return;
}
int longestLength = 0;
for (int i = 0; i < m->itemCount; i++) {
if (m->items[i].label) {
int currentLength = strlen(m->items[i].label);
if (currentLength > longestLength) {
longestLength = currentLength;
}
}
}
/*
(char)134 = lbracket
(char)135 = rbracket
Double line borders:
(char)130 = top lcorner
(char)128 = hpipe
(char)132 = top rcorner
(char)129 = vpipe
(char)131 = bot lcorner
(char)133 = bot rcorner
Single line borders:
(char)138 = top lcorner
(char)136 = hpipe
(char)140 = top rcorner
(char)137 = vpipe
(char)139 = bot lcorner
(char)141 = bot rcorner
*/
iprintf("\x1B[30m\x1b[%d;%dH%c%c%c%s%c", 1 + level, level + 1, (char)138, (char)136, (char)134, m->lheader, (char)135);
for (int j = 0; j < longestLength - 3 - strlen(m->lheader); j++) {
printf("%c", (char)136);
}
printf("%c\n", (char)140);
//items
for (int i = 0; i < m->itemCount; i++)
{
if (m->items[i].label)
{
if (m->items[i].directory)
iprintf(" [%.28s]\n", m->items[i].label);
else
iprintf(" %.30s\n", m->items[i].label);
if (m->items[i].directory) {
iprintf("\x1b[%d;%dH%c[%.28s]", i + 2 + level, level + 1, (char)137, m->items[i].label);
for (int j = strlen(m->items[i].label); j < longestLength; j++) {
printf(" ");
}
printf("%c\n", (char)137);
} else {
iprintf("\x1b[%d;%dH%c%.30s", i + 2 + level, level + 1, (char)137, m->items[i].label);
for (int j = strlen(m->items[i].label); j < longestLength; j++) {
printf(" ");
}
printf("%c\n", (char)137);
}
}
else
else {
iprintf(" \n");
}
}
iprintf("\x1b[%d;%dH%c", m->itemCount + 2 + level, level + 1, (char)139);
for (int j = 0; j < longestLength; j++) {
printf("%c", (char)136);
}
printf("%c\n", (char)141);
//cursor
iprintf("\x1b[%d;0H>", 2 + m->cursor);
iprintf("\x1b[%d;%dH%c\x1B[41m%s\x1B[30m\x1b[%dC%c", m->cursor + 2 + level, level + 1, (char)137, m->items[m->cursor].label, longestLength - strlen(m->items[m->cursor].label), (char)137);
//scroll arrows
if (m->page > 0)
@ -225,4 +337,12 @@ bool moveCursor(Menu* m)
}
return !(lastCursor == m->cursor);
}
char downloadPlayLoading(int number) {
char pictoload[] = {(char)142, (char)143, (char)144, (char)145, (char)146, (char)147, (char)148, (char)149};
static int counter = 0;
counter = (counter % 7) + 1;
return pictoload[counter];
}

View File

@ -9,6 +9,7 @@ typedef struct {
bool directory;
char* label;
char* value;
char* help;
} Item;
typedef struct {
@ -18,20 +19,26 @@ typedef struct {
bool nextPage;
int changePage;
char header[32];
char lheader[32];
Item items[ITEMS_PER_PAGE];
} Menu;
Menu* newMenu();
void freeMenu(Menu* m);
void addMenuItem(Menu* m, char const* label, char const* value, bool directory);
void addMenuItem(Menu* m, char const* label, char const* value, bool directory, char const* help);
void sortMenuItems(Menu* m);
void setMenuHeader(Menu* m, char* str);
void setListHeader(Menu* m, char* str);
void resetMenu(Menu* m);
void clearMenu(Menu* m);
void printMenu(Menu* m);
void clearHelpMenu(Menu* m);
void printHelpMenu(Menu* m);
void printMenu(Menu* m, int level);
bool moveCursor(Menu* m);
char downloadPlayLoading(int number);
#endif

View File

@ -23,7 +23,7 @@ bool choiceBox(char* message)
iprintf("\x1B[33m"); //yellow
iprintf("%s\n", message);
iprintf("\x1B[40m"); //white
iprintf("\x1B[30m"); //white
iprintf("\x1b[%d;0H\tYes\n\tNo\n", choiceRow);
while (!programEnd)
@ -60,7 +60,7 @@ bool choicePrint(char* message)
iprintf("\x1B[34m"); //yellow
iprintf("\n%s\n", message);
iprintf("\x1B[40m"); //white
iprintf("\x1B[30m"); //white
iprintf("Yes - [A]\nNo - [B]\n");
while (!programEnd)
@ -103,7 +103,7 @@ bool randomConfirmBox(char* message)
iprintf("\x1B[43m"); //yellow
iprintf("%s\n", message);
iprintf("\x1B[40m"); //white
iprintf("\x1B[30m"); //white
iprintf("\n<START> cancel\n");
while (!programEnd && sequencePosition < sizeof(sequence))

View File

@ -50,6 +50,46 @@ u8 vbrPhoto[54] = {
0x20, 0x20, 0x20, 0x20, 0x20, 0x20
};
// File tables for /sys/ folder and HWInfo secure
// Why? HWInfo is always at one of 3 set offsets. I use those offsets for HWInfo recovery.
// We will copy over these file tables to ensure the offsets stay the same.
// No idea what this is but I need it lol
u8 fileTable1[16] = {
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00
};
// File table for /sys/ folder
u8 fileTable2[64] = {
0x41, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F,
0x00, 0x54, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x53, 0x59, 0x53, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
0x21, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00
};
// File table for HWInfo
u8 fileTable3[192] = {
0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x00, 0x00, 0x00, 0x00, 0x75, 0x02,
0x64, 0x59, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x2E, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
0x21, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xE5, 0x6C, 0x00, 0x6F, 0x00, 0x67, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xE5, 0x4F, 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x00, 0x00, 0x01, 0x00, 0x21, 0x28, 0x64, 0x59, 0x00, 0x00, 0x01, 0x00,
0x21, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x48, 0x00, 0x57,
0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x0F, 0x00, 0x9C, 0x4F, 0x00,
0x5F, 0x00, 0x53, 0x00, 0x2E, 0x00, 0x64, 0x00, 0x61, 0x00, 0x00, 0x00,
0x74, 0x00, 0x00, 0x00, 0x48, 0x57, 0x49, 0x4E, 0x46, 0x4F, 0x5F, 0x53,
0x44, 0x41, 0x54, 0x20, 0x00, 0x00, 0x01, 0x00, 0x21, 0x28, 0x64, 0x59,
0x00, 0x00, 0x50, 0x02, 0x64, 0x59, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00
};
static size_t i;
enum {
@ -62,28 +102,22 @@ enum {
static int _fsMenu(int cursor)
{
//top screen
clearScreen(cMAIN);
printf("\n\x1B[40mTwlNandTool Ver0.0");
printf("\n\nNAND repair tool by RMC/RVTR");
printf("\n\nMode: FileSystem");
//menu
Menu* m = newMenu();
setMenuHeader(m, "TwlNandTool");
Menu* m = newMenu();
setMenuHeader(m, "TwlNandTool");
setListHeader(m, "FileSystem");
char modeStr[32];
addMenuItem(m, "Read MBR", NULL, 0);
addMenuItem(m, "Repair MBR", NULL, 0);
addMenuItem(m, "Format TWL_MAIN", NULL, 0);
addMenuItem(m, "Format TWL_PHOTO", NULL, 0);
addMenuItem(m, "Back", NULL, 0);
addMenuItem(m, "Read MBR", NULL, 0, "Test the Master Boot Record.");
addMenuItem(m, "Repair MBR", NULL, 0, "Repair the Master Boot Record.");
addMenuItem(m, "Format TWL_MAIN", NULL, 0, "Format the partition where the\n firmware, apps, and saves are\n installed.\n\n THIS WILL ERASE EVERYTHING.");
addMenuItem(m, "Format TWL_PHOTO", NULL, 0, "Format the partition where\n photos are stored.\n\n THIS WILL ERASE EVERYTHING.");
addMenuItem(m, "Back", NULL, 0, "Leave the FileSystem menu.");
m->cursor = cursor;
//bottom screen
printMenu(m);
printMenu(m, 1);
while (!programEnd)
{
@ -91,7 +125,7 @@ static int _fsMenu(int cursor)
scanKeys();
if (moveCursor(m))
printMenu(m);
printMenu(m, 1);
if (keysDown() & KEY_A)
break;
@ -128,7 +162,7 @@ int fsMain(void)
break;
case FORMAT_PHOTO:
repairMbr();
formatPhoto();
break;
case BACK:
@ -162,7 +196,7 @@ int readMbr(void) {
}
}
if(parse_mbr(sector_buf, is3DS)) {
iprintf("\n\n \x1B[31mERROR!\x1B[40m MBR is corrupted.");
iprintf("\n\n \x1B[31mERROR!\x1B[30m MBR is corrupted.");
}
iprintf("\n\n Please Push Select To Return ");
@ -213,11 +247,11 @@ int repairMbr(void) {
dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
if(parse_mbr(sector_buf, is3DS)) {
iprintf("\n\n \x1B[31mERROR!\x1B[40m Failed to fix MBR.");
iprintf("\n\n \x1B[31mERROR!\x1B[30m Failed to fix MBR.");
} else {
iprintf("\n\x1B[32mThe new MBR passed!\x1B[30m");
}
iprintf("\n\x1B[32mThe new MBR passed!\x1B[40m");
iprintf("\n\n Please Push Select To Return ");
while (true)
@ -233,18 +267,69 @@ int repairMbr(void) {
int formatMain(void) {
clearScreen(cSUB);
iprintf("\n>> Write TWL_MAIN VBR ");
iprintf("\n>> Format TWL_MAIN ");
iprintf("\n--------------------------------");
iprintf("\n\nWriting VBR...");
memset(file_buf, 0, 0x200);
// Write the first 54 bytes, then pad to 0x1FE. Finally write 0x55AA
memcpy(file_buf, vbrMain, sizeof(vbrMain));
memset(file_buf + sizeof(vbrMain), 0, (BUFFER_SIZE - sizeof(vbrMain) - 2));
memset(file_buf + SECTOR_SIZE - 2, 0x55, 1);
memset(file_buf + SECTOR_SIZE - 1, 0xAA, 1);
good_nandio_write(0x10EE00, 0x200, file_buf, false);
good_nandio_write(0x10EE00, 0x200, file_buf, true);
iprintf("\nClearing file tables...");
memset(file_buf, 0, 0x600);
for (i = 0; i < 0x3d8; i++) {
good_nandio_write(0x10EE00 + 0x200 + (0x600 * i), 0x600, file_buf, true);
}
iprintf("\nMaking new file tables...");
memset(file_buf, 0, 0x200);
memcpy(file_buf, fileTable1, sizeof(fileTable1));
good_nandio_write(0x115800, sizeof(fileTable1), file_buf, true);
memset(file_buf, 0, 0x200);
memcpy(file_buf, fileTable2, sizeof(fileTable2));
good_nandio_write(0x11C000, sizeof(fileTable2), file_buf, true);
memset(file_buf, 0, 0x200);
memcpy(file_buf, fileTable3, sizeof(fileTable3));
good_nandio_write(0x120000, sizeof(fileTable3), file_buf, true);
iprintf("\nAll done!");
iprintf("\n\n Please Push Select To Return ");
while (true)
{
swiWaitForVBlank();
scanKeys();
if (keysDown() & KEY_SELECT )
break;
}
}
int formatPhoto(void) {
clearScreen(cSUB);
iprintf("\n>> Format TWL_PHOTO ");
iprintf("\n--------------------------------");
iprintf("\n\nWriting VBR...");
memset(file_buf, 0, 0x200);
// Write the first 54 bytes, then pad to 0x1FE. Finally write 0x55AA
memcpy(file_buf, vbrPhoto, sizeof(vbrPhoto));
memset(file_buf + sizeof(vbrPhoto), 0, (BUFFER_SIZE - sizeof(vbrPhoto) - 2));
memset(file_buf + SECTOR_SIZE - 2, 0x55, 1);
memset(file_buf + SECTOR_SIZE - 1, 0xAA, 1);
good_nandio_write(0xCF09A00, 0x200, file_buf, true);
iprintf("\nClearing file tables...");
memset(file_buf, 0, 0x200);
for (i = 0; i < 0x13A; i++) {
good_nandio_write(0xCF09A00 + 0x200 + (0x200 * i), 0x200, file_buf, true);
}
iprintf("\nAll done!");
iprintf("\n\nDone! Please confirm VBR is correct.");
iprintf("\n\n Please Push Select To Return ");
while (true)

View File

@ -18,4 +18,5 @@
int fsMain(void);
int readMbr(void);
int repairMbr(void);
int formatMain(void);
int formatMain(void);
int formatPhoto(void);

View File

@ -14,7 +14,7 @@
#include "../main.h"
#include "../video.h"
u32 done=0;
bool success = true;
void death(char *message, u8 *buffer){
iprintf("\n%s\n", message);
@ -34,28 +34,22 @@ enum {
static int _nfMenu(int cursor)
{
//top screen
clearScreen(cMAIN);
printf("\n\x1B[40mTwlNandTool Ver0.0");
printf("\n\nNAND repair tool by RMC/RVTR");
printf("\n\nMode: NandFirm");
//menu
Menu* m = newMenu();
setMenuHeader(m, "TwlNandTool");
Menu* m = newMenu();
setMenuHeader(m, "TwlNandTool");
setListHeader(m, "NandFirm");
char modeStr[32];
addMenuItem(m, "Check NandFirm", NULL, 0);
addMenuItem(m, "Import NandFirm", NULL, 0);
addMenuItem(m, "Import NandFirm (SDMC)", NULL, 0);
addMenuItem(m, "CID Info", NULL, 0);
addMenuItem(m, "Back", NULL, 0);
addMenuItem(m, "Check NandFirm", NULL, 0, "Check the stage2 (bootloader)\n version and type.");
addMenuItem(m, "Import NandFirm", NULL, 0, "Install the standard stage2\n (bootloader).\n\n This stage2 works normally,\n but it is an updated version:\n - v2265-9336 (prod)\n - v2725-9336 (dev)");
addMenuItem(m, "Import NandFirm (SDMC)", NULL, 0, "Install the SDMC Launcher\n stage2 (bootloader).\n\n SDMC will remove access to\n the firmware and SHOULD NOT\n BE USED unless otherwise\n told to do so.");
addMenuItem(m, "CID Info", NULL, 0, "Get NAND chip information.");
addMenuItem(m, "Back", NULL, 0, "Leave the NandFirm menu.");
m->cursor = cursor;
//bottom screen
printMenu(m);
printMenu(m, 1);
while (!programEnd)
{
@ -63,7 +57,7 @@ static int _nfMenu(int cursor)
scanKeys();
if (moveCursor(m))
printMenu(m);
printMenu(m, 1);
if (keysDown() & KEY_A)
break;
@ -130,10 +124,12 @@ int nandFirmRead(void) {
}
printf("\n Ver: ");
for (i = 0; i < 9; i++) {
for (i = 0; i < 10; i++) {
if (sector_buf[i] == 0x0A) {
printf("-");
} else if (sector_buf[i] == 0x0D) {
printf("");
} else {
printf("%c", sector_buf[i]);
}
@ -151,14 +147,14 @@ int nandFirmRead(void) {
if (keysDown() & KEY_SELECT )
break;
}
return success;
}
int nandFirmImport(bool sdmc) {
bool nandFirmImport(bool sdmc) {
clearScreen(cSUB);
iprintf("\n>> Debug1");
iprintf("\n NandFirm write ");
iprintf("\n>> Import NandFirm (%s) ", sdmc ? "sdmc" : "menu");
iprintf("\n--------------------------------");
printf("Opening NandFirm...\n");
@ -167,7 +163,7 @@ int nandFirmImport(bool sdmc) {
snprintf(file_path, 100, "nitro:/import/%s/%s-launcher.nand", consoleSignName, sdmc ? "sdmc" : "menu");
FILE *file = fopen(file_path, "r");
printf("%s\n", file_path);
printf("\n%s\n\n", file_path);
if(file) {
// First 0x200 of NandFirm is reserved for MBR
@ -178,8 +174,13 @@ int nandFirmImport(bool sdmc) {
good_nandio_write_file(0x200, file_length - ftell(file), file, false);
printf("Done!\n");
fclose(file);
} else {
success = false;
iprintf("\nNandFirm import failed!");
}
iprintf("\n\n Please Push Select To Return ");
while (true)
{
swiWaitForVBlank();
@ -188,6 +189,7 @@ int nandFirmImport(bool sdmc) {
if (keysDown() & KEY_SELECT )
break;
}
return success;
}
int nandPrintInfo(void) {
@ -224,4 +226,5 @@ int nandPrintInfo(void) {
if (keysDown() & KEY_SELECT )
break;
}
return success;
}

View File

@ -20,5 +20,5 @@ void death(char *message, u8 *buffer);
int nfMain(void);
int nandFirmRead(void);
int nandFirmImport(bool sdmc);
bool nandFirmImport(bool sdmc);
int nandPrintInfo(void);

View File

@ -7,6 +7,7 @@
#include "sector0.h"
#include "f_xy.h"
#include "nandio.h"
#include "../menu.h"
#include "u128_math.h"
/************************ Function Protoypes **********************************/
@ -50,6 +51,8 @@ static u32 fat_sig_fix_offset = 0;
static u32 sector_buf32[SECTOR_SIZE/sizeof(u32)];
extern u8 *sector_buf = (u8*)sector_buf32;
static u32 sector_buf232[SECTOR_SIZE/sizeof(u32)];
extern u8 *sector_buf2 = (u8*)sector_buf232;
static u32 file_buf32[BUFFER_SIZE/sizeof(u32)];
extern u8 *file_buf = (u8*)file_buf32;
@ -253,18 +256,23 @@ bool good_nandio_write(int inputAddress, int inputLength, u8 *buffer, bool crypt
int byteEndOffset = (inputAddress+inputLength) % SECTOR_SIZE;
int sectorEndNum = (inputAddress+inputLength) / SECTOR_SIZE;
int i;
if (inputLength <= 0x200) {
if (inputLength <= SECTOR_SIZE) {
// Handle a single sector write differently since it is unpredictable
nand_ReadSectors(sectorNum, 1, sector_buf);
memcpy(sector_buf, buffer, inputLength);
if (crypt == true) {
dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
dsi_nand_crypt(sector_buf, sector_buf, sectorNum * SECTOR_SIZE / AES_BLOCK_SIZE, SECTOR_SIZE / AES_BLOCK_SIZE);
}
nand_WriteSectors(sectorNum, 1, sector_buf);
//iprintf("\n%02X to %02X of %02X", byteOffset, inputLength, sectorNum);
//iprintf("\n%02X to %02X of buffer", 0, inputLength);
} else {
iprintf("\n ");
for (i = sectorNum; i < sectorEndNum + 1;) {
char currentPicto = downloadPlayLoading(i);
if (i % (sectorEndNum / 15) == 0) {
printf("\b%c", currentPicto);
}
// Back up sector
nand_ReadSectors(i, 1, sector_buf);
if (i == sectorNum) {
@ -286,12 +294,17 @@ bool good_nandio_write(int inputAddress, int inputLength, u8 *buffer, bool crypt
// I need to do a cmp here t0 save NAND writes
// Write sector
if (crypt == true) {
dsi_nand_crypt(buffer, buffer, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
// offset * SECTOR_SIZE / AES_BLOCK_SIZE
dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)0x2FFD7BC, is3DS);
dsi_nand_crypt(sector_buf, sector_buf, i * SECTOR_SIZE / AES_BLOCK_SIZE, SECTOR_SIZE / AES_BLOCK_SIZE);
// Okay so the below one encrypted every other sector, failing the 1st, 3rd, 5th, etc.
//dsi_nand_crypt(sector_buf, sector_buf, inputAddress * SECTOR_SIZE / AES_BLOCK_SIZE, SECTOR_SIZE / AES_BLOCK_SIZE);
}
nand_WriteSectors(i, 1, sector_buf);
i++;
// Do some check to make sure it is not outside of NAND range.
}
iprintf("\b\x1B[1A");
}
return true;
}
@ -303,17 +316,22 @@ bool good_nandio_write_file(int inputAddress, int inputLength, FILE *fp, bool cr
int sectorEndNum = (inputAddress+inputLength) / SECTOR_SIZE;
int i;
u8 buffer[SECTOR_SIZE];
if (inputLength <= 0x200) {
if (inputLength <= SECTOR_SIZE) {
// Handle a single sector write differently since it is unpredictable
nand_ReadSectors(sectorNum, 1, sector_buf);
fread(buffer, 1, inputLength, fp);
memcpy(sector_buf, buffer, inputLength);
if (crypt == true) {
dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
dsi_nand_crypt(sector_buf, sector_buf, sectorNum * SECTOR_SIZE / AES_BLOCK_SIZE, SECTOR_SIZE / AES_BLOCK_SIZE);
}
nand_WriteSectors(sectorNum, 1, sector_buf);
} else {
iprintf("\n ");
for (i = sectorNum; i < sectorEndNum + 1;) {
char currentPicto = downloadPlayLoading(i);
if (i % (sectorEndNum / 15) == 0) {
printf("\b%c", currentPicto);
}
// Back up sector
nand_ReadSectors(i, 1, sector_buf);
@ -333,12 +351,13 @@ bool good_nandio_write_file(int inputAddress, int inputLength, FILE *fp, bool cr
// I need to do a cmp here t0 save NAND writes
// Write sector
if (crypt == true) {
dsi_nand_crypt(buffer, buffer, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
dsi_nand_crypt(sector_buf, sector_buf, i * SECTOR_SIZE / AES_BLOCK_SIZE, SECTOR_SIZE / AES_BLOCK_SIZE);
}
nand_WriteSectors(i, 1, sector_buf);
i++;
// Do some check to make sure it is not outside of NAND range.
}
iprintf("\b\x1B[1A");
}
return true;
}

View File

@ -38,7 +38,7 @@ void printProgressBar(float percent)
{
consoleSet(cMAIN);
iprintf("\x1B[42m"); //green
iprintf("\x1B[32m"); //green
//Print frame
if (lastBars <= 0)
@ -291,7 +291,7 @@ bool copyDir(char const* src, char const* dst)
}
else
{
iprintf("\x1B[42m"); //green
iprintf("\x1B[32m"); //green
iprintf("Done\n");
iprintf("\x1B[47m"); //white
}
@ -357,7 +357,7 @@ bool deleteDir(char const* path)
}
else
{
iprintf("\x1B[42m");
iprintf("\x1B[32m");
iprintf("Done\n");
iprintf("\x1B[47m");
}
@ -377,7 +377,7 @@ bool deleteDir(char const* path)
}
else
{
iprintf("\x1B[42m");
iprintf("\x1B[32m");
iprintf("Done\n");
iprintf("\x1B[47m");
}

View File

@ -4,6 +4,7 @@
// From https://code.google.com/archive/p/sundevos/
// common headers
#include "video.h"
#include "font.h"
#define SUB ((u16 *)BG_BMP_RAM_SUB(2))
#define MAIN ((u16 *)BG_BMP_RAM(2))
@ -17,89 +18,31 @@ PrintConsole console, consoleSub;
*/
void videoInit() {
consoleDebugInit(DebugDevice_CONSOLE); // debug to console
videoSetMode(MODE_5_3D);
vramSetBankA(VRAM_A_MAIN_BG_0x06000000); // allocate 128Ko at 0x06000000
videoSetMode(MODE_0_2D);
videoSetModeSub(MODE_0_2D);
vramSetBankA (VRAM_A_MAIN_BG);
vramSetBankC (VRAM_C_SUB_BG);
// <-- console (debug console for binaries loaded)
consoleInit(
&console, // the console to be initted
1, // bgLayer
BgType_Text4bpp, // bg type
BgSize_T_256x256, // bg size
4, // map base
0, // tile base
true, // main display
true // load graphics
);
iprintf("\x1b[32;1m"); // Set the color to green
// --> <-- 2D (96Ko at 0x06008000)
bgInit(
3, // bg layer
BgType_Bmp16, // bg type
BgSize_B16_256x256, // bg size
2, // map base (here it's the bmp base)
0 // tile base (here it's useless)
);
screenFill(MAIN, RGB15(31, 31, 31)|BIT(15));
// --> <-- 3D
/* <-- old
glInit();
glClearColor(0,0,0,0); // make the BG transparent
glClearDepth(0x7FFF);
glViewport(0,0,255,191); // Set our viewport to be the same size as the screen
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, 256.0 / 192.0, 0.1, 100);
--> */
bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 1, 0);
bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 1, 0);
#define MIN_X (0.0f)
#define MAX_X (4.0f)
#define MIN_Y (0.0f)
#define MAX_Y (3.0f)
glInit();
glClearColor(0,0,0,0); // BG must be opaque for AA to work
//glClearPolyID(63); // BG must have a unique polygon ID for AA to work
glClearDepth(0x7FFF);
glViewport(0,0,255,191);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof32(floattof32(MIN_X), floattof32(MAX_X), floattof32(MIN_Y), floattof32(MAX_Y), floattof32(0.1), floattof32(10));
glMatrixMode(GL_MODELVIEW);
glMaterialf(GL_AMBIENT, RGB15(31,31,31));
glMaterialf(GL_DIFFUSE, RGB15(31,31,31));
glMaterialf(GL_SPECULAR, BIT(15) | RGB15(31,31,31));
glMaterialf(GL_EMISSION, RGB15(31,31,31));
glMaterialShinyness();
glMatrixMode(GL_MODELVIEW);
// -->
consoleInit(&consoleSub, 3, BgType_Text4bpp, BgSize_T_256x256, 20, 0, false, false);
consoleInit(&console, 3, BgType_Text4bpp, BgSize_T_256x256, 20, 0, true, false);
videoSetModeSub(MODE_5_2D);
vramSetBankC(VRAM_C_SUB_BG_0x06200000); // allocate 128Ko at 0x06200000
ConsoleFont font;
font.gfx = (u16*)fontTiles;
font.pal = (u16*)fontPal;
font.numChars = 200;
font.numColors = fontPalLen / 2;
font.bpp = 4;
font.asciiOffset = 32;
font.convertSingleColor = true;
consoleSetFont(&console, &font);
consoleSetFont(&consoleSub, &font);
// <-- console (debug console for SunOS)
consoleInit(
&consoleSub, // the console to be initted
1, // bgLayer
BgType_Text4bpp, // bg type
BgSize_T_256x256, // bg size
4, // map base
0, // tile base
false, // main display
true // load graphics
);
iprintf("\x1b[31;1m"); // Set the color to red
// --> <-- 2D (96Ko at 0x06208000)
bgInitSub(
3, // bg layer
BgType_Bmp16, // bg type
BgSize_B16_256x256, // bg size
2, // map base (here it's the bmp base)
0 // tile base (here it's useless)
);
screenFill(SUB, RGB15(31, 31, 31)|BIT(15));
// -->
setBackdropColor(0xFFFF);
setBackdropColorSub(0xFFFF);
lcdMainOnBottom();
consoleSet(cSUB);