Formatting

This commit is contained in:
Maschell 2021-10-17 15:28:14 +02:00
parent 80110c3f4c
commit f972091f50
9 changed files with 206 additions and 194 deletions

View File

@ -39,7 +39,7 @@ void ApplicationState::changeState(eGameState newState) {
menu.addText(std::string(appInfo->appName)); menu.addText(std::string(appInfo->appName));
menu.addText(); menu.addText();
menu.addText("Additional informations:"); menu.addText("Additional informations:");
auto showCheckResult = [&] (const std::string &name, bool canPatch, bool patched) { auto showCheckResult = [&](const std::string &name, bool canPatch, bool patched) {
if (patched) { if (patched) {
menu.addText("[ X ] " + name + " is already patched!"); menu.addText("[ X ] " + name + " is already patched!");
} else if (canPatch) { } else if (canPatch) {
@ -133,7 +133,7 @@ void ApplicationState::changeState(eGameState newState) {
menu.addText("System is currently booting into: "); menu.addText("System is currently booting into: ");
std::string titleId = StringTools::strfmt("%ll016X", this->coldbootTitleId); std::string titleId = StringTools::strfmt("%ll016X", this->coldbootTitleId);
std::string titleName = this->coldbootTitle ? std::string titleName = this->coldbootTitle ?
std::string(this->coldbootTitle->name) : "Unknown title"; std::string(this->coldbootTitle->name) : "Unknown title";
menu.addText(titleId + " (" + titleName + ")"); menu.addText(titleId + " (" + titleName + ")");
menu.addText(); menu.addText();
if (this->systemXMLRestorePossible && this->systemXMLAlreadyPatched) { if (this->systemXMLRestorePossible && this->systemXMLAlreadyPatched) {
@ -211,7 +211,7 @@ void ApplicationState::update(Input *input) {
} }
} else if (this->state == STATE_INSTALL_FST) { } else if (this->state == STATE_INSTALL_FST) {
auto result = (this->fstAlreadyPatched) ? InstallerService::SUCCESS : auto result = (this->fstAlreadyPatched) ? InstallerService::SUCCESS :
InstallerService::patchFST(this->appInfo->path, this->appInfo->fstHash); InstallerService::patchFST(this->appInfo->path, this->appInfo->fstHash);
if (result != InstallerService::SUCCESS) { if (result != InstallerService::SUCCESS) {
this->installerError = result; this->installerError = result;
setError(ERROR_INSTALLER_ERROR); setError(ERROR_INSTALLER_ERROR);
@ -220,7 +220,7 @@ void ApplicationState::update(Input *input) {
} }
} else if (this->state == STATE_INSTALL_COS) { } else if (this->state == STATE_INSTALL_COS) {
auto result = (this->cosAlreadyPatched) ? InstallerService::SUCCESS : auto result = (this->cosAlreadyPatched) ? InstallerService::SUCCESS :
InstallerService::patchCOS(this->appInfo->path, this->appInfo->cosHash); InstallerService::patchCOS(this->appInfo->path, this->appInfo->cosHash);
if (result != InstallerService::SUCCESS) { if (result != InstallerService::SUCCESS) {
this->installerError = result; this->installerError = result;
setError(ERROR_INSTALLER_ERROR); setError(ERROR_INSTALLER_ERROR);

View File

@ -37,7 +37,7 @@ InstallerService::eResults InstallerService::checkCOS(const std::string &path, c
DEBUG_FUNCTION_LINE("Success! cos.xml is compatible"); DEBUG_FUNCTION_LINE("Success! cos.xml is compatible");
return SUCCESS; return SUCCESS;
} else { } else {
DEBUG_FUNCTION_LINE("Hash mismatch! cos.xml is NOT compatible. Expected hash: %s actual hash: %s",hash, newHash.c_str()); DEBUG_FUNCTION_LINE("Hash mismatch! cos.xml is NOT compatible. Expected hash: %s actual hash: %s", hash, newHash.c_str());
} }
return COS_XML_HASH_MISMATCH; return COS_XML_HASH_MISMATCH;
@ -203,8 +203,7 @@ std::optional<uint64_t> InstallerService::getSystemMenuTitleId() {
if ((titleList->titleId != 0x0005001010040000L) && if ((titleList->titleId != 0x0005001010040000L) &&
(titleList->titleId != 0x0005001010040100L) && (titleList->titleId != 0x0005001010040100L) &&
(titleList->titleId != 0x0005001010040200L)) (titleList->titleId != 0x0005001010040200L)) {
{
DEBUG_FUNCTION_LINE("Unrecognized System Menu title"); DEBUG_FUNCTION_LINE("Unrecognized System Menu title");
return {}; return {};
} }
@ -349,12 +348,12 @@ std::string InstallerService::ErrorMessage(InstallerService::eResults error) {
bool InstallerService::isBackupAvailable(const std::string &path) { bool InstallerService::isBackupAvailable(const std::string &path) {
std::string backupList[] = { std::string backupList[] = {
{"/content/title.fst.bak"}, {"/content/title.fst.bak"},
{"/content/cos.xml.bak" }, {"/content/cos.xml.bak"},
{"/content/safe.rpx.bak" }, {"/content/safe.rpx.bak"},
}; };
for (auto &backupEntry : backupList) { for (auto &backupEntry: backupList) {
std::string backupFile = path + backupEntry; std::string backupFile = path + backupEntry;
std::string backupSha1 = backupFile + ".sha1"; std::string backupSha1 = backupFile + ".sha1";
@ -385,12 +384,12 @@ bool InstallerService::isBackupAvailable(const std::string &path) {
InstallerService::eResults InstallerService::restoreAppFiles(const std::string &path) { InstallerService::eResults InstallerService::restoreAppFiles(const std::string &path) {
std::string backupList[][2] = { std::string backupList[][2] = {
{"/code/title.fst", "/content/title.fst.bak"}, {"/code/title.fst", "/content/title.fst.bak"},
{"/code/cos.xml", "/content/cos.xml.bak" }, {"/code/cos.xml", "/content/cos.xml.bak"},
{"/code/safe.rpx", "/content/safe.rpx.bak" }, {"/code/safe.rpx", "/content/safe.rpx.bak"},
}; };
for (auto &backupOp : backupList) { for (auto &backupOp: backupList) {
std::string destPath = path + backupOp[0]; std::string destPath = path + backupOp[0];
std::string backupPath = path + backupOp[1]; std::string backupPath = path + backupOp[1];
@ -407,7 +406,7 @@ InstallerService::eResults InstallerService::restoreAppFiles(const std::string &
} }
} }
for (auto &backupOp : backupList) { for (auto &backupOp: backupList) {
std::string backupPath = path + backupOp[1]; std::string backupPath = path + backupOp[1];
std::string backupSha1Path = backupPath + ".sha1"; std::string backupSha1Path = backupPath + ".sha1";
::remove(backupPath.c_str()); ::remove(backupPath.c_str());
@ -420,12 +419,12 @@ InstallerService::eResults InstallerService::restoreAppFiles(const std::string &
InstallerService::eResults InstallerService::backupAppFiles(const std::string &path) { InstallerService::eResults InstallerService::backupAppFiles(const std::string &path) {
std::string backupList[][2] = { std::string backupList[][2] = {
{"/code/title.fst", "/content/title.fst.bak"}, {"/code/title.fst", "/content/title.fst.bak"},
{"/code/cos.xml", "/content/cos.xml.bak" }, {"/code/cos.xml", "/content/cos.xml.bak"},
{"/code/safe.rpx", "/content/safe.rpx.bak" }, {"/code/safe.rpx", "/content/safe.rpx.bak"},
}; };
for (auto &backupOp : backupList) { for (auto &backupOp: backupList) {
std::string backupSrc = path + backupOp[0]; std::string backupSrc = path + backupOp[0];
std::string backupDst = path + backupOp[1]; std::string backupDst = path + backupOp[1];
std::string backupSha1 = backupDst + ".sha1"; std::string backupSha1 = backupDst + ".sha1";
@ -726,7 +725,7 @@ InstallerService::eResults InstallerService::checkTMDValid(const std::string &pa
InstallerService::eResults result = checkFileHash(filePath, hash); InstallerService::eResults result = checkFileHash(filePath, hash);
if(result != SUCCESS){ if (result != SUCCESS) {
// In some cases the tmd seems to have cert appended // In some cases the tmd seems to have cert appended
return checkFileHash(filePath, tmdWithCertHash); return checkFileHash(filePath, tmdWithCertHash);
} }

View File

@ -29,7 +29,7 @@ public:
FAILED_TO_LOAD_FILE = -18, FAILED_TO_LOAD_FILE = -18,
}; };
static bool isColdBootAllowed(){ static bool isColdBootAllowed() {
if (OSIsAddressValid(0x00FFFFF8)) { if (OSIsAddressValid(0x00FFFFF8)) {
uint64_t bootedFrom = *((uint64_t *) 0x00FFFFF8); uint64_t bootedFrom = *((uint64_t *) 0x00FFFFF8);
if ( if (

View File

@ -7,7 +7,7 @@
#include "utils/WiiUScreen.h" #include "utils/WiiUScreen.h"
#include "utils/ScreenUtils.h" #include "utils/ScreenUtils.h"
template <typename T> template<typename T>
class Menu { class Menu {
public: public:
Menu() { Menu() {
@ -45,7 +45,7 @@ public:
int selectedDist = selected; int selectedDist = selected;
WiiUScreen::clearScreen(); WiiUScreen::clearScreen();
printHeader(); printHeader();
for (auto &row : content) { for (auto &row: content) {
std::string cursor = ""; std::string cursor = "";
if (row.first) { if (row.first) {
cursor += (selectedDist--) ? " " : "> "; cursor += (selectedDist--) ? " " : "> ";

View File

@ -12,7 +12,7 @@ systemXMLInformation systemXMLHashInformation[] = {
appInformation supportedApps[] = { appInformation supportedApps[] = {
{0x000500101004E000L, "Health and Safety Information [JPN]", false, {'\0'}, "9D34DDD91604D781FDB0727AC75021833304964C", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "D5BABA20526524977009F7EDE25182D8E41CEFD8", "2CF358E1F51932D305911A6836ED37DB0F94ABE4"}, //v129 {0x000500101004E000L, "Health and Safety Information [JPN]", false, {'\0'}, "9D34DDD91604D781FDB0727AC75021833304964C", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "D5BABA20526524977009F7EDE25182D8E41CEFD8", "2CF358E1F51932D305911A6836ED37DB0F94ABE4"}, //v129
{0x000500101004E100L, "Health and Safety Information [USA]", false, {'\0'}, "045734666A36C7EF0258A740855886EBDB20D59B", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "5249DA6B75FEFADEBFBB18ECC93CC109FA8AA630", "C53C219FB8F777F9AB8F430D6BE4BC034D5638BA"}, //v129 {0x000500101004E100L, "Health and Safety Information [USA]", false, {'\0'}, "045734666A36C7EF0258A740855886EBDB20D59B", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "5249DA6B75FEFADEBFBB18ECC93CC109FA8AA630", "C53C219FB8F777F9AB8F430D6BE4BC034D5638BA"}, //v129
{0x000500101004E200L, "Health and Safety Information [PAL]", false, {'\0'}, "130A76F8B36B36D43B88BBC74393D9AFD9CFD2A4", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "87749A8D3EE8694225423953DCF04B01F8DA2F15", "4A29A60E5FBDAF410B7C22ECAEBDDBF29D1A874E"}, //v129 {0x000500101004E200L, "Health and Safety Information [PAL]", false, {'\0'}, "130A76F8B36B36D43B88BBC74393D9AFD9CFD2A4", "F6EBF7BC8AE3AF3BB8A42E0CF3FDA051278AEB03", "87749A8D3EE8694225423953DCF04B01F8DA2F15", "4A29A60E5FBDAF410B7C22ECAEBDDBF29D1A874E"}, //v129
{0, nullptr, false, {'\0'}, {'\0'}, {'\0'}}, {0, nullptr, false, {'\0'}, {'\0'}, {'\0'}},
}; };

View File

@ -51,5 +51,6 @@ public:
private: private:
ScreenUtils() = default; ScreenUtils() = default;
~ScreenUtils() = default; ~ScreenUtils() = default;
}; };

View File

@ -89,7 +89,7 @@ public:
static bool findStringIC(const std::string &strHaystack, const std::string &strNeedle); static bool findStringIC(const std::string &strHaystack, const std::string &strNeedle);
// https://stackoverflow.com/a/3418285 // https://stackoverflow.com/a/3418285
static bool replace(std::string& str, const std::string& from, const std::string& to); static bool replace(std::string &str, const std::string &from, const std::string &to);
static bool strCompareIC(const std::string &str1, const std::string &str2); static bool strCompareIC(const std::string &str1, const std::string &str2);
}; };

View File

@ -21,176 +21,188 @@
*/ */
#ifndef _TINY_SHA1_HPP_ #ifndef _TINY_SHA1_HPP_
#define _TINY_SHA1_HPP_ #define _TINY_SHA1_HPP_
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <stdint.h> #include <stdint.h>
namespace sha1
{ namespace sha1 {
class SHA1 class SHA1 {
{ public:
public: typedef uint32_t digest32_t[5];
typedef uint32_t digest32_t[5]; typedef uint8_t digest8_t[20];
typedef uint8_t digest8_t[20];
inline static uint32_t LeftRotate(uint32_t value, size_t count) { inline static uint32_t LeftRotate(uint32_t value, size_t count) {
return (value << count) ^ (value >> (32-count)); return (value << count) ^ (value >> (32 - count));
} }
SHA1(){ reset(); }
virtual ~SHA1() {} SHA1() { reset(); }
SHA1(const SHA1& s) { *this = s; }
const SHA1& operator = (const SHA1& s) { virtual ~SHA1() {}
memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
memcpy(m_block, s.m_block, 64); SHA1(const SHA1 &s) { *this = s; }
m_blockByteIndex = s.m_blockByteIndex;
m_byteCount = s.m_byteCount; const SHA1 &operator=(const SHA1 &s) {
return *this; memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
} memcpy(m_block, s.m_block, 64);
SHA1& reset() { m_blockByteIndex = s.m_blockByteIndex;
m_digest[0] = 0x67452301; m_byteCount = s.m_byteCount;
m_digest[1] = 0xEFCDAB89; return *this;
m_digest[2] = 0x98BADCFE; }
m_digest[3] = 0x10325476;
m_digest[4] = 0xC3D2E1F0; SHA1 &reset() {
m_blockByteIndex = 0; m_digest[0] = 0x67452301;
m_byteCount = 0; m_digest[1] = 0xEFCDAB89;
return *this; m_digest[2] = 0x98BADCFE;
} m_digest[3] = 0x10325476;
SHA1& processByte(uint8_t octet) { m_digest[4] = 0xC3D2E1F0;
this->m_block[this->m_blockByteIndex++] = octet; m_blockByteIndex = 0;
++this->m_byteCount; m_byteCount = 0;
if(m_blockByteIndex == 64) { return *this;
this->m_blockByteIndex = 0; }
processBlock();
} SHA1 &processByte(uint8_t octet) {
return *this; this->m_block[this->m_blockByteIndex++] = octet;
} ++this->m_byteCount;
SHA1& processBlock(const void* const start, const void* const end) { if (m_blockByteIndex == 64) {
const uint8_t* begin = static_cast<const uint8_t*>(start); this->m_blockByteIndex = 0;
const uint8_t* finish = static_cast<const uint8_t*>(end); processBlock();
while(begin != finish) { }
processByte(*begin); return *this;
begin++; }
}
return *this; SHA1 &processBlock(const void *const start, const void *const end) {
} const uint8_t *begin = static_cast<const uint8_t *>(start);
SHA1& processBytes(const void* const data, size_t len) { const uint8_t *finish = static_cast<const uint8_t *>(end);
const uint8_t* block = static_cast<const uint8_t*>(data); while (begin != finish) {
processBlock(block, block + len); processByte(*begin);
return *this; begin++;
} }
const uint32_t* getDigest(digest32_t digest) { return *this;
size_t bitCount = this->m_byteCount * 8; }
processByte(0x80);
if (this->m_blockByteIndex > 56) { SHA1 &processBytes(const void *const data, size_t len) {
while (m_blockByteIndex != 0) { const uint8_t *block = static_cast<const uint8_t *>(data);
processByte(0); processBlock(block, block + len);
} return *this;
while (m_blockByteIndex < 56) { }
processByte(0);
} const uint32_t *getDigest(digest32_t digest) {
} else { size_t bitCount = this->m_byteCount * 8;
while (m_blockByteIndex < 56) { processByte(0x80);
processByte(0); if (this->m_blockByteIndex > 56) {
} while (m_blockByteIndex != 0) {
} processByte(0);
processByte(0); }
processByte(0); while (m_blockByteIndex < 56) {
processByte(0); processByte(0);
processByte(0); }
processByte( static_cast<unsigned char>((bitCount>>24) & 0xFF)); } else {
processByte( static_cast<unsigned char>((bitCount>>16) & 0xFF)); while (m_blockByteIndex < 56) {
processByte( static_cast<unsigned char>((bitCount>>8 ) & 0xFF)); processByte(0);
processByte( static_cast<unsigned char>((bitCount) & 0xFF)); }
}
memcpy(digest, m_digest, 5 * sizeof(uint32_t)); processByte(0);
return digest; processByte(0);
} processByte(0);
const uint8_t* getDigestBytes(digest8_t digest) { processByte(0);
digest32_t d32; processByte(static_cast<unsigned char>((bitCount >> 24) & 0xFF));
getDigest(d32); processByte(static_cast<unsigned char>((bitCount >> 16) & 0xFF));
size_t di = 0; processByte(static_cast<unsigned char>((bitCount >> 8) & 0xFF));
digest[di++] = ((d32[0] >> 24) & 0xFF); processByte(static_cast<unsigned char>((bitCount) & 0xFF));
digest[di++] = ((d32[0] >> 16) & 0xFF);
digest[di++] = ((d32[0] >> 8) & 0xFF); memcpy(digest, m_digest, 5 * sizeof(uint32_t));
digest[di++] = ((d32[0]) & 0xFF); return digest;
}
digest[di++] = ((d32[1] >> 24) & 0xFF);
digest[di++] = ((d32[1] >> 16) & 0xFF); const uint8_t *getDigestBytes(digest8_t digest) {
digest[di++] = ((d32[1] >> 8) & 0xFF); digest32_t d32;
digest[di++] = ((d32[1]) & 0xFF); getDigest(d32);
size_t di = 0;
digest[di++] = ((d32[2] >> 24) & 0xFF); digest[di++] = ((d32[0] >> 24) & 0xFF);
digest[di++] = ((d32[2] >> 16) & 0xFF); digest[di++] = ((d32[0] >> 16) & 0xFF);
digest[di++] = ((d32[2] >> 8) & 0xFF); digest[di++] = ((d32[0] >> 8) & 0xFF);
digest[di++] = ((d32[2]) & 0xFF); digest[di++] = ((d32[0]) & 0xFF);
digest[di++] = ((d32[3] >> 24) & 0xFF); digest[di++] = ((d32[1] >> 24) & 0xFF);
digest[di++] = ((d32[3] >> 16) & 0xFF); digest[di++] = ((d32[1] >> 16) & 0xFF);
digest[di++] = ((d32[3] >> 8) & 0xFF); digest[di++] = ((d32[1] >> 8) & 0xFF);
digest[di++] = ((d32[3]) & 0xFF); digest[di++] = ((d32[1]) & 0xFF);
digest[di++] = ((d32[4] >> 24) & 0xFF); digest[di++] = ((d32[2] >> 24) & 0xFF);
digest[di++] = ((d32[4] >> 16) & 0xFF); digest[di++] = ((d32[2] >> 16) & 0xFF);
digest[di++] = ((d32[4] >> 8) & 0xFF); digest[di++] = ((d32[2] >> 8) & 0xFF);
digest[di++] = ((d32[4]) & 0xFF); digest[di++] = ((d32[2]) & 0xFF);
return digest;
} digest[di++] = ((d32[3] >> 24) & 0xFF);
digest[di++] = ((d32[3] >> 16) & 0xFF);
protected: digest[di++] = ((d32[3] >> 8) & 0xFF);
void processBlock() { digest[di++] = ((d32[3]) & 0xFF);
uint32_t w[80];
for (size_t i = 0; i < 16; i++) { digest[di++] = ((d32[4] >> 24) & 0xFF);
w[i] = (m_block[i*4 + 0] << 24); digest[di++] = ((d32[4] >> 16) & 0xFF);
w[i] |= (m_block[i*4 + 1] << 16); digest[di++] = ((d32[4] >> 8) & 0xFF);
w[i] |= (m_block[i*4 + 2] << 8); digest[di++] = ((d32[4]) & 0xFF);
w[i] |= (m_block[i*4 + 3]); return digest;
} }
for (size_t i = 16; i < 80; i++) {
w[i] = LeftRotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1); protected:
} void processBlock() {
uint32_t w[80];
uint32_t a = m_digest[0]; for (size_t i = 0; i < 16; i++) {
uint32_t b = m_digest[1]; w[i] = (m_block[i * 4 + 0] << 24);
uint32_t c = m_digest[2]; w[i] |= (m_block[i * 4 + 1] << 16);
uint32_t d = m_digest[3]; w[i] |= (m_block[i * 4 + 2] << 8);
uint32_t e = m_digest[4]; w[i] |= (m_block[i * 4 + 3]);
}
for (std::size_t i=0; i<80; ++i) { for (size_t i = 16; i < 80; i++) {
uint32_t f = 0; w[i] = LeftRotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
uint32_t k = 0; }
if (i<20) { uint32_t a = m_digest[0];
f = (b & c) | (~b & d); uint32_t b = m_digest[1];
k = 0x5A827999; uint32_t c = m_digest[2];
} else if (i<40) { uint32_t d = m_digest[3];
f = b ^ c ^ d; uint32_t e = m_digest[4];
k = 0x6ED9EBA1;
} else if (i<60) { for (std::size_t i = 0; i < 80; ++i) {
f = (b & c) | (b & d) | (c & d); uint32_t f = 0;
k = 0x8F1BBCDC; uint32_t k = 0;
} else {
f = b ^ c ^ d; if (i < 20) {
k = 0xCA62C1D6; f = (b & c) | (~b & d);
} k = 0x5A827999;
uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i]; } else if (i < 40) {
e = d; f = b ^ c ^ d;
d = c; k = 0x6ED9EBA1;
c = LeftRotate(b, 30); } else if (i < 60) {
b = a; f = (b & c) | (b & d) | (c & d);
a = temp; k = 0x8F1BBCDC;
} } else {
f = b ^ c ^ d;
m_digest[0] += a; k = 0xCA62C1D6;
m_digest[1] += b; }
m_digest[2] += c; uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i];
m_digest[3] += d; e = d;
m_digest[4] += e; d = c;
} c = LeftRotate(b, 30);
private: b = a;
digest32_t m_digest; a = temp;
uint8_t m_block[64]; }
size_t m_blockByteIndex;
size_t m_byteCount; m_digest[0] += a;
}; m_digest[1] += b;
m_digest[2] += c;
m_digest[3] += d;
m_digest[4] += e;
}
private:
digest32_t m_digest;
uint8_t m_block[64];
size_t m_blockByteIndex;
size_t m_byteCount;
};
} }
#endif #endif

View File

@ -24,7 +24,7 @@ void Utils::dumpHex(const void *data, size_t size) {
if ((i + 1) % 16 == 0) { if ((i + 1) % 16 == 0) {
WHBLogPrintf("| %s ", ascii); WHBLogPrintf("| %s ", ascii);
if (i + 1 < size) { if (i + 1 < size) {
DEBUG_FUNCTION_LINE("0x%08X (0x%04X); ", ((uint32_t)data) + i + 1, i + 1); DEBUG_FUNCTION_LINE("0x%08X (0x%04X); ", ((uint32_t) data) + i + 1, i + 1);
} }
} else if (i + 1 == size) { } else if (i + 1 == size) {
ascii[(i + 1) % 16] = '\0'; ascii[(i + 1) % 16] = '\0';