Skip to content

Commit

Permalink
Refactor string handling
Browse files Browse the repository at this point in the history
  • Loading branch information
TuxSH committed May 7, 2017
1 parent f5aa639 commit e8d4a98
Show file tree
Hide file tree
Showing 14 changed files with 546 additions and 162 deletions.
38 changes: 19 additions & 19 deletions source/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)

initScreens();

drawString(CONFIG_TITLE, true, 10, 10, COLOR_TITLE);
drawString("Press A to select, START to save", true, 10, 10 + SPACING_Y, COLOR_TITLE);
drawString(true, 10, 10, COLOR_TITLE, CONFIG_TITLE);
drawString(true, 10, 10 + SPACING_Y, COLOR_TITLE, "Press A to select, START to save");

//Character to display a selected option
char selected = 'x';
Expand All @@ -260,8 +260,8 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
if(!multiOptions[i].visible) continue;

multiOptions[i].posY = endPos + SPACING_Y;
endPos = drawString(multiOptionsText[i], true, 10, multiOptions[i].posY, COLOR_WHITE);
drawCharacter(selected, true, 10 + multiOptions[i].posXs[multiOptions[i].enabled] * SPACING_X, multiOptions[i].posY, COLOR_WHITE);
endPos = drawString(true, 10, multiOptions[i].posY, COLOR_WHITE, multiOptionsText[i]);
drawCharacter(true, 10 + multiOptions[i].posXs[multiOptions[i].enabled] * SPACING_X, multiOptions[i].posY, COLOR_WHITE, selected);
}

endPos += SPACING_Y / 2;
Expand All @@ -272,8 +272,8 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
if(!singleOptions[i].visible) continue;

singleOptions[i].posY = endPos + SPACING_Y;
endPos = drawString(singleOptionsText[i], true, 10, singleOptions[i].posY, color);
if(singleOptions[i].enabled) drawCharacter(selected, true, 10 + SPACING_X, singleOptions[i].posY, color);
endPos = drawString(true, 10, singleOptions[i].posY, color, singleOptionsText[i]);
if(singleOptions[i].enabled) drawCharacter(true, 10 + SPACING_X, singleOptions[i].posY, color, selected);

if(color == COLOR_RED)
{
Expand All @@ -283,7 +283,7 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
}
}

drawString(optionsDescription[selectedOption], false, 10, 10, COLOR_WHITE);
drawString(false, 10, 10, COLOR_WHITE, optionsDescription[selectedOption]);

//Boring configuration menu
while(true)
Expand Down Expand Up @@ -347,29 +347,29 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
//The user moved to a different option, print the old option in white and the new one in red. Only print 'x's if necessary
if(oldSelectedOption < multiOptionsAmount)
{
drawString(multiOptionsText[oldSelectedOption], true, 10, multiOptions[oldSelectedOption].posY, COLOR_WHITE);
drawCharacter(selected, true, 10 + multiOptions[oldSelectedOption].posXs[multiOptions[oldSelectedOption].enabled] * SPACING_X, multiOptions[oldSelectedOption].posY, COLOR_WHITE);
drawString(true, 10, multiOptions[oldSelectedOption].posY, COLOR_WHITE, multiOptionsText[oldSelectedOption]);
drawCharacter(true, 10 + multiOptions[oldSelectedOption].posXs[multiOptions[oldSelectedOption].enabled] * SPACING_X, multiOptions[oldSelectedOption].posY, COLOR_WHITE, selected);
}
else
{
u32 singleOldSelected = oldSelectedOption - multiOptionsAmount;
drawString(singleOptionsText[singleOldSelected], true, 10, singleOptions[singleOldSelected].posY, COLOR_WHITE);
if(singleOptions[singleOldSelected].enabled) drawCharacter(selected, true, 10 + SPACING_X, singleOptions[singleOldSelected].posY, COLOR_WHITE);
drawString(true, 10, singleOptions[singleOldSelected].posY, COLOR_WHITE, singleOptionsText[singleOldSelected]);
if(singleOptions[singleOldSelected].enabled) drawCharacter(true, 10 + SPACING_X, singleOptions[singleOldSelected].posY, COLOR_WHITE, selected);
}

if(isMultiOption) drawString(multiOptionsText[selectedOption], true, 10, multiOptions[selectedOption].posY, COLOR_RED);
else drawString(singleOptionsText[singleSelected], true, 10, singleOptions[singleSelected].posY, COLOR_RED);
if(isMultiOption) drawString(true, 10, multiOptions[selectedOption].posY, COLOR_RED, multiOptionsText[selectedOption]);
else drawString(true, 10, singleOptions[singleSelected].posY, COLOR_RED, singleOptionsText[singleSelected]);

drawString(optionsDescription[oldSelectedOption], false, 10, 10, COLOR_BLACK);
drawString(optionsDescription[selectedOption], false, 10, 10, COLOR_WHITE);
drawString(false, 10, 10, COLOR_BLACK, optionsDescription[oldSelectedOption]);
drawString(false, 10, 10, COLOR_WHITE, optionsDescription[selectedOption]);
}
else
{
//The selected option's status changed, print the 'x's accordingly
if(isMultiOption)
{
u32 oldEnabled = multiOptions[selectedOption].enabled;
drawCharacter(selected, true, 10 + multiOptions[selectedOption].posXs[oldEnabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_BLACK);
drawCharacter(true, 10 + multiOptions[selectedOption].posXs[oldEnabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_BLACK, selected);
multiOptions[selectedOption].enabled = (oldEnabled == 3 || !multiOptions[selectedOption].posXs[oldEnabled + 1]) ? 0 : oldEnabled + 1;

if(selectedOption == BRIGHTNESS) updateBrightness(multiOptions[BRIGHTNESS].enabled);
Expand All @@ -378,13 +378,13 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
{
bool oldEnabled = singleOptions[singleSelected].enabled;
singleOptions[singleSelected].enabled = !oldEnabled;
if(oldEnabled) drawCharacter(selected, true, 10 + SPACING_X, singleOptions[singleSelected].posY, COLOR_BLACK);
if(oldEnabled) drawCharacter(true, 10 + SPACING_X, singleOptions[singleSelected].posY, COLOR_BLACK, selected);
}
}

//In any case, if the current option is enabled (or a multiple choice option is selected) we must display a red 'x'
if(isMultiOption) drawCharacter(selected, true, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED);
else if(singleOptions[singleSelected].enabled) drawCharacter(selected, true, 10 + SPACING_X, singleOptions[singleSelected].posY, COLOR_RED);
if(isMultiOption) drawCharacter(true, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED, selected);
else if(singleOptions[singleSelected].enabled) drawCharacter(true, 10 + SPACING_X, singleOptions[singleSelected].posY, COLOR_RED, selected);
}

//Preserve the last-used boot options (first 9 bits)
Expand Down
21 changes: 17 additions & 4 deletions source/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "utils.h"
#include "fs.h"
#include "font.h"
#include <stdarg.h>
#include "fmt.h"

bool loadSplash(void)
{
Expand All @@ -57,7 +59,7 @@ bool loadSplash(void)
return true;
}

void drawCharacter(char character, bool isTopScreen, u32 posX, u32 posY, u32 color)
void drawCharacter(bool isTopScreen, u32 posX, u32 posY, u32 color, char character)
{
u8 *select = isTopScreen ? fbs[0].top_left : fbs[0].bottom;

Expand All @@ -77,7 +79,7 @@ void drawCharacter(char character, bool isTopScreen, u32 posX, u32 posY, u32 col
}
}

u32 drawString(const char *string, bool isTopScreen, u32 posX, u32 posY, u32 color)
u32 drawString(bool isTopScreen, u32 posX, u32 posY, u32 color, const char *string)
{
for(u32 i = 0, line_i = 0; i < strlen(string); i++)
switch(string[i])
Expand All @@ -100,11 +102,22 @@ u32 drawString(const char *string, bool isTopScreen, u32 posX, u32 posY, u32 col
if(string[i] == ' ') break; //Spaces at the start look weird
}

drawCharacter(string[i], isTopScreen, posX + line_i * SPACING_X, posY, color);
drawCharacter(isTopScreen, posX + line_i * SPACING_X, posY, color, string[i]);

line_i++;
break;
}

return posY;
}
}

u32 drawFormattedString(bool isTopScreen, u32 posX, u32 posY, u32 color, const char *fmt, ...)
{
char buf[DRAW_MAX_FORMATTED_STRING_SIZE + 1];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);

return drawString(isTopScreen, posX, posY, color, buf);
}
7 changes: 5 additions & 2 deletions source/draw.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#define COLOR_BLACK 0x000000
#define COLOR_YELLOW 0x00FFFF

#define DRAW_MAX_FORMATTED_STRING_SIZE 512

bool loadSplash(void);
void drawCharacter(char character, bool isTopScreen, u32 posX, u32 posY, u32 color);
u32 drawString(const char *string, bool isTopScreen, u32 posX, u32 posY, u32 color);
void drawCharacter(bool isTopScreen, u32 posX, u32 posY, u32 color, char character);
u32 drawString(bool isTopScreen, u32 posX, u32 posY, u32 color, const char *string);
u32 drawFormattedString(bool isTopScreen, u32 posX, u32 posY, u32 color, const char *fmt, ...);
90 changes: 37 additions & 53 deletions source/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "screen.h"
#include "draw.h"
#include "utils.h"
#include "fmt.h"
#include "../build/bundled.h"

void installArm9Handlers(void)
Expand Down Expand Up @@ -119,107 +120,90 @@ void detectAndProcessExceptionDumps(void)
};

const char *specialExceptions[] = {
"(kernel panic)", "(svcBreak)"
"kernel panic", "svcBreak"
};

const char *registerNames[] = {
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12",
"SP", "LR", "PC", "CPSR", "FPEXC"
};

char hexString[] = "00000000";

initScreens();

drawString("An exception occurred", true, 10, 10, COLOR_RED);
u32 posY = drawString(dumpHeader->processor == 11 ? "Processor: ARM11 (core )" : "Processor: ARM9", true, 10, 30, COLOR_WHITE);
if(dumpHeader->processor == 11) drawCharacter('0' + dumpHeader->core, true, 10 + 29 * SPACING_X, 30, COLOR_WHITE);

posY = drawString("Exception type: ", true, 10, posY + SPACING_Y, COLOR_WHITE);
drawString(handledExceptionNames[dumpHeader->type], true, 10 + 17 * SPACING_X, posY, COLOR_WHITE);
drawString(true, 10, 10, COLOR_RED, "An exception occurred");
u32 posY;
if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: ARM11 (core %u)", dumpHeader->core);
else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: ARM9");

if(dumpHeader->type == 2)
{
if((regs[16] & 0x20) == 0 && dumpHeader->codeDumpSize >= 4)
{
u32 instr = *(vu32 *)(stackDump - 4);
if(instr == 0xE12FFF7E) drawString(specialExceptions[0], true, 10 + 32 * SPACING_X, posY, COLOR_WHITE);
else if(instr == 0xEF00003C) drawString(specialExceptions[1], true, 10 + 32 * SPACING_X, posY, COLOR_WHITE);
if(instr == 0xE12FFF7E)
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s (%s)", handledExceptionNames[dumpHeader->type], specialExceptions[0]);
else if(instr == 0xEF00003C)
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s (%s)", handledExceptionNames[dumpHeader->type], specialExceptions[1]);
else
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s", handledExceptionNames[dumpHeader->type]);
}
else if((regs[16] & 0x20) != 0 && dumpHeader->codeDumpSize >= 2)
{
u16 instr = *(vu16 *)(stackDump - 2);
if(instr == 0xDF3C) drawString(specialExceptions[1], true, 10 + 32 * SPACING_X, posY, COLOR_WHITE);
if(instr == 0xDF3C)
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s (%s)", handledExceptionNames[dumpHeader->type], specialExceptions[0]);
else
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s", handledExceptionNames[dumpHeader->type]);
}
}
else
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s", handledExceptionNames[dumpHeader->type]);

if(dumpHeader->processor == 11 && dumpHeader->additionalDataSize != 0)
{
char processName[45] = "Current process: ";
memcpy(processName + 17, (void *)additionalData, 8);
hexItoa(*(vu32 *)(additionalData + 12), hexString, 8, true);
concatenateStrings(processName, " (");
concatenateStrings(processName, hexString);
hexItoa(*(vu32 *)(additionalData + 8), hexString, 8, true);
concatenateStrings(processName, hexString);
concatenateStrings(processName, ")");
posY = drawString(processName, true, 10, posY + SPACING_Y, COLOR_WHITE);
}

posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE,
"Current process: %.8s (%016llX)", (const char *)additionalData, *(vu64 *)(additionalData + 8));
posY += SPACING_Y;

for(u32 i = 0; i < 17; i += 2)
{
posY = drawString(registerNames[i], true, 10, posY + SPACING_Y, COLOR_WHITE);
hexItoa(regs[i], hexString, 8, true);
drawString(hexString, true, 10 + 7 * SPACING_X, posY, COLOR_WHITE);
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08X", registerNames[i], regs[i]);

if(i != 16 || dumpHeader->processor != 9)
{
drawString(registerNames[i + 1], true, 10 + 22 * SPACING_X, posY, COLOR_WHITE);
hexItoa(i == 16 ? regs[20] : regs[i + 1], hexString, 8, true);
drawString(hexString, true, 10 + 29 * SPACING_X, posY, COLOR_WHITE);
}
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08X", registerNames[i + 1], regs[i + 1]);
}

posY += SPACING_Y;

u32 mode = regs[16] & 0xF;
if(dumpHeader->type == 3 && (mode == 7 || mode == 11))
posY = drawString("Incorrect dump: failed to dump code and/or stack", true, 10, posY + SPACING_Y, COLOR_YELLOW) + SPACING_Y;
posY = drawString(true, 10, posY + SPACING_Y, COLOR_YELLOW, "Incorrect dump: failed to dump code and/or stack") + SPACING_Y;

u32 posYBottom = drawString("Stack dump:", false, 10, 10, COLOR_WHITE) + SPACING_Y;
u32 posYBottom = drawString(false, 10, 10, COLOR_WHITE, "Stack dump:") + SPACING_Y;

for(u32 line = 0; line < 19 && stackDump < additionalData; line++)
{
hexItoa(regs[13] + 8 * line, hexString, 8, true);
posYBottom = drawString(hexString, false, 10, posYBottom + SPACING_Y, COLOR_WHITE);
drawCharacter(':', false, 10 + 8 * SPACING_X, posYBottom, COLOR_WHITE);
posYBottom = drawFormattedString(false, 10, posYBottom + SPACING_Y, COLOR_WHITE, "%08X:", regs[13] + 8 * line);

for(u32 i = 0; i < 8 && stackDump < additionalData; i++, stackDump++)
{
char byteString[] = "00";
hexItoa(*stackDump, byteString, 2, false);
drawString(byteString, false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE);
}
drawFormattedString(false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE, "%02X", *stackDump);
}

char path[36] = "dumps/",
fileName[] = "crash_dump_00000000.dmp";

concatenateStrings(path, dumpHeader->processor == 9 ? "arm9" : "arm11");
findDumpFile(path, fileName);
concatenateStrings(path, "/");
concatenateStrings(path, fileName);
char folderPath[36],
path[36],
fileName[] = "crash_dump_00010000.dmp";

sprintf(folderPath, "dumps/arm%u", dumpHeader->processor);
findDumpFile(folderPath, fileName);
sprintf(path, "%s/%s", folderPath, fileName);

if(fileWrite((void *)dumpHeader, path, dumpHeader->totalSize))
{
posY = drawString("You can find a dump in the following file:", true, 10, posY + SPACING_Y, COLOR_WHITE);
posY = drawString(path, true, 10, posY + SPACING_Y, COLOR_WHITE) + SPACING_Y;
posY = drawString(true, 10, posY + SPACING_Y, COLOR_WHITE, "You can find a dump in the following file:");
posY = drawString(true, 10, posY + SPACING_Y, COLOR_WHITE, path) + SPACING_Y;
}
else posY = drawString("Error writing the dump file", true, 10, posY + SPACING_Y, COLOR_RED);
else posY = drawString(true, 10, posY + SPACING_Y, COLOR_RED, "Error writing the dump file");

drawString("Press any button to shutdown", true, 10, posY + SPACING_Y, COLOR_WHITE);
drawString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Press any button to shutdown");

memset32((void *)dumpHeader, 0, dumpHeader->totalSize);

Expand Down
8 changes: 4 additions & 4 deletions source/firm.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "emunand.h"
#include "crypto.h"
#include "screen.h"
#include "fmt.h"
#include "../build/bundled.h"

static Firm *firm = (Firm *)0x24000000;
Expand Down Expand Up @@ -325,11 +326,10 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType, boo

if(loadFromStorage)
{
char fileName[24] = "sysmodules/";
char fileName[64];

//Read modules from files if they exist
concatenateStrings(fileName, moduleName);
concatenateStrings(fileName, ".cxi");
sprintf(fileName, "%.8s.cxi", moduleName);

dstModuleSize = getFileSize(fileName);

Expand All @@ -349,7 +349,7 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType, boo

const u8 *module;

if(firmType == NATIVE_FIRM && memcmp(moduleName, "loader", 6) == 0)
if(firmType == NATIVE_FIRM && memcmp(moduleName, "loader", 6 + 1) == 0)
{
module = injector_bin;
dstModuleSize = injector_bin_size;
Expand Down

0 comments on commit e8d4a98

Please sign in to comment.