
- transform some error codes into "NAND damaged" or "Gamecard removed" like official errdisp does - fix bug in SetUserString - add more info to logfile (/luma/errdisp.txt)
164 lines
5.0 KiB
C
164 lines
5.0 KiB
C
/*
|
|
* This file is part of Luma3DS
|
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
* * Requiring preservation of specified reasonable legal notices or
|
|
* author attributions in that material or in the Appropriate Legal
|
|
* Notices displayed by works containing it.
|
|
* * Prohibiting misrepresentation of the origin of that material,
|
|
* or requiring that modified versions of such material be marked in
|
|
* reasonable ways as different from the original version.
|
|
*/
|
|
|
|
#include "utils.h"
|
|
#include "csvc.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
void formatMemoryPermission(char *outbuf, MemPerm perm)
|
|
{
|
|
if (perm == MEMPERM_DONTCARE)
|
|
{
|
|
strcpy(outbuf, "???");
|
|
return;
|
|
}
|
|
|
|
outbuf[0] = perm & MEMPERM_READ ? 'r' : '-';
|
|
outbuf[1] = perm & MEMPERM_WRITE ? 'w' : '-';
|
|
outbuf[2] = perm & MEMPERM_EXECUTE ? 'x' : '-';
|
|
outbuf[3] = '\0';
|
|
}
|
|
|
|
void formatUserMemoryState(char *outbuf, MemState state)
|
|
{
|
|
static const char *states[12] =
|
|
{
|
|
"Free",
|
|
"Reserved",
|
|
"IO",
|
|
"Static",
|
|
"Code",
|
|
"Private",
|
|
"Shared",
|
|
"Continuous",
|
|
"Aliased",
|
|
"Alias",
|
|
"AliasCode",
|
|
"Locked"
|
|
};
|
|
|
|
strcpy(outbuf, state > 11 ? "Unknown" : states[state]);
|
|
}
|
|
|
|
u32 formatMemoryMapOfProcess(char *outbuf, u32 bufLen, Handle handle)
|
|
{
|
|
u32 maxLineSize = 35 + (handle == CUR_PROCESS_HANDLE ? 15 : 0);
|
|
u32 address = 0;
|
|
u32 posInBuffer = 0;
|
|
u32 maxPosInBuffer = bufLen - maxLineSize; // 35 is the maximum length of a formatted region
|
|
MemInfo memi;
|
|
PageInfo pagei;
|
|
char pabuf[32];
|
|
char permbuf[8];
|
|
char statebuf[16];
|
|
|
|
s64 TTBCR;
|
|
svcGetSystemInfo(&TTBCR, 0x10002, 0);
|
|
|
|
while (address < (1u << (32 - (u32)TTBCR)) // Limit to check for regions
|
|
&& posInBuffer < maxPosInBuffer
|
|
&& R_SUCCEEDED(svcQueryProcessMemory(&memi, &pagei, handle, address)))
|
|
{
|
|
// Update the address for next region
|
|
address = memi.base_addr + memi.size;
|
|
|
|
// If region isn't FREE then add it to the list
|
|
if (memi.state != MEMSTATE_FREE)
|
|
{
|
|
if (handle == CUR_PROCESS_HANDLE)
|
|
{
|
|
u32 pa = svcConvertVAToPA((void *)memi.base_addr, false);
|
|
sprintf(pabuf, " (PA %08lx)", pa);
|
|
}
|
|
else
|
|
pabuf[0] = '\0';
|
|
|
|
formatMemoryPermission(permbuf, memi.perm);
|
|
formatUserMemoryState(statebuf, memi.state);
|
|
|
|
posInBuffer += sprintf(outbuf + posInBuffer, "%08lx - %08lx%s %s %s\n",
|
|
memi.base_addr, address, pabuf, permbuf, statebuf);
|
|
}
|
|
}
|
|
|
|
svcCloseHandle(handle);
|
|
return posInBuffer;
|
|
}
|
|
|
|
int dateTimeToString(char *out, u64 msSince1900, bool filenameFormat)
|
|
{
|
|
// Conversion code adapted from https://stackoverflow.com/questions/21593692/convert-unix-timestamp-to-date-without-system-libs
|
|
// (original author @gnif under CC-BY-SA 4.0)
|
|
u32 seconds, minutes, hours, days, year, month;
|
|
u64 milliseconds = msSince1900;
|
|
seconds = milliseconds/1000;
|
|
milliseconds %= 1000;
|
|
minutes = seconds / 60;
|
|
seconds %= 60;
|
|
hours = minutes / 60;
|
|
minutes %= 60;
|
|
days = hours / 24;
|
|
hours %= 24;
|
|
|
|
year = 1900; // osGetTime starts in 1900
|
|
|
|
while(true)
|
|
{
|
|
bool leapYear = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
|
|
u16 daysInYear = leapYear ? 366 : 365;
|
|
if(days >= daysInYear)
|
|
{
|
|
days -= daysInYear;
|
|
++year;
|
|
}
|
|
else
|
|
{
|
|
static const u8 daysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
|
for(month = 0; month < 12; ++month)
|
|
{
|
|
u8 dim = daysInMonth[month];
|
|
|
|
if (month == 1 && leapYear)
|
|
++dim;
|
|
|
|
if (days >= dim)
|
|
days -= dim;
|
|
else
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
days++;
|
|
month++;
|
|
|
|
if (filenameFormat)
|
|
return sprintf(out, "%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu", year, month, days, hours, minutes, seconds, milliseconds);
|
|
else
|
|
return sprintf(out, "%04lu-%02lu-%02lu %02lu:%02lu:%02lu", year, month, days, hours, minutes, seconds);
|
|
}
|