578 lines
21 KiB
C++
578 lines
21 KiB
C++
#include <cli-fancy.hpp>
|
|
#include <cmath>
|
|
#include <ctrff.hpp>
|
|
#include <format>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <map>
|
|
#include <palladium>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
/** Import palladium stb image */
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
#include <pd/external/stb_image.h>
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
#include <stb_image_write.h>
|
|
/** Could not use the palladium func due to only using headers */
|
|
const std::string FormatBytes(unsigned long long bytes) {
|
|
if (bytes == 1) {
|
|
// Only one Byte
|
|
return std::format("{} Byte", bytes);
|
|
} else if (bytes < 1024) {
|
|
// less than one kilobyte
|
|
return std::format("{} Bytes", bytes);
|
|
} else if (bytes < 1048576) {
|
|
// less than one megabyte
|
|
return std::format("{:.1f} KB", (float)bytes / 1024.f);
|
|
} else if (bytes < 1073741824) {
|
|
// less than one gigabyte
|
|
return std::format("{:.1f} MB", (float)bytes / 1048576.f);
|
|
} else {
|
|
// gigabyte
|
|
return std::format("{:.1f} GB", (float)bytes / 1073741824.f);
|
|
}
|
|
}
|
|
|
|
const std::map<ctrff::SMDH::Language, std::string> smdh_lang_table = {
|
|
{ctrff::SMDH::Language_Japanese, "Japanese"},
|
|
{ctrff::SMDH::Language_English, "English"},
|
|
{ctrff::SMDH::Language_French, "French"},
|
|
{ctrff::SMDH::Language_German, "German"},
|
|
{ctrff::SMDH::Language_Italian, "Italian"},
|
|
{ctrff::SMDH::Language_Spanish, "Spanish"},
|
|
{ctrff::SMDH::Language_Chinese_Simplified, "Chinese Simplified"},
|
|
{ctrff::SMDH::Language_Korean, "Korean"},
|
|
{ctrff::SMDH::Language_Dutch, "Dutch"},
|
|
{ctrff::SMDH::Language_Portuguese, "Portuguese"},
|
|
{ctrff::SMDH::Language_Russian, "Russian"},
|
|
{ctrff::SMDH::Language_Chinese_Traditional, "Chinese Traditional"},
|
|
};
|
|
|
|
const std::map<ctrff::SMDH::Rating, std::string> smdh_rating_table = {
|
|
{ctrff::SMDH::Rating_CERO, "CERO"},
|
|
{ctrff::SMDH::Rating_ESRB, "ESRB"},
|
|
{ctrff::SMDH::Rating_USK, "USK"},
|
|
{ctrff::SMDH::Rating_PEGI_GEN, "PEGI_GEN"},
|
|
{ctrff::SMDH::Rating_PEGI_PTR, "PEGI_PTR"},
|
|
{ctrff::SMDH::Rating_PEGI_BBFC, "PEGI_BBFC"},
|
|
{ctrff::SMDH::Rating_COB, "COB"},
|
|
{ctrff::SMDH::Rating_GRB, "GRB"},
|
|
{ctrff::SMDH::Rating_CGSRR, "CGSRR"},
|
|
};
|
|
|
|
const std::map<ctrff::SMDH::Region, std::string> smdh_region_table = {
|
|
{ctrff::SMDH::Region_JAPAN, "Japan"},
|
|
{ctrff::SMDH::Region_NORTH_AMERICA, "North America"},
|
|
{ctrff::SMDH::Region_EUROPE, "Europe"},
|
|
{ctrff::SMDH::Region_AUSTRALIA, "Australia"},
|
|
{ctrff::SMDH::Region_CHINA, "China"},
|
|
{ctrff::SMDH::Region_KOREA, "Korea"},
|
|
{ctrff::SMDH::Region_TAIWAN, "Taiwan"},
|
|
{ctrff::SMDH::Region_FREE, "Free"},
|
|
};
|
|
|
|
const std::map<ctrff::SMDH::Flag, std::string> smdh_flag_table{
|
|
{ctrff::SMDH::Flag_VISIBLE, "Visible"},
|
|
{ctrff::SMDH::Flag_AUTO_BOOT, "Auto Boot"},
|
|
{ctrff::SMDH::Flag_ALLOW_3D, "Allow 3D"},
|
|
{ctrff::SMDH::Flag_REQUIRE_EULA, "Require EULA"},
|
|
{ctrff::SMDH::Flag_AUTO_SAVE_ON_EXIT, "Auto Save on Exit"},
|
|
{ctrff::SMDH::Flag_USE_EXTENDED_BANNER, "Use Extended Banner"},
|
|
{ctrff::SMDH::Flag_RATING_REQUIED, "Rating required"},
|
|
{ctrff::SMDH::Flag_USE_SAVE_DATA, "Use Save Data"},
|
|
{ctrff::SMDH::Flag_RECORD_USAGE, "Record usage"},
|
|
{ctrff::SMDH::Flag_DISABLE_SAVE_BACKUPS, "Disable Save backups"},
|
|
{ctrff::SMDH::Flag_NEW_3DS, "New 3DS"},
|
|
};
|
|
|
|
const std::map<std::string, ctrff::SMDH::Language> smdh_lang_stropts = {
|
|
{"", ctrff::SMDH::Language_All},
|
|
{"jp", ctrff::SMDH::Language_Japanese},
|
|
{"en", ctrff::SMDH::Language_English},
|
|
{"fr", ctrff::SMDH::Language_French},
|
|
{"de", ctrff::SMDH::Language_German},
|
|
{"it", ctrff::SMDH::Language_Italian},
|
|
{"es", ctrff::SMDH::Language_Spanish},
|
|
{"cs", ctrff::SMDH::Language_Chinese_Simplified},
|
|
{"ko", ctrff::SMDH::Language_Korean},
|
|
{"du", ctrff::SMDH::Language_Dutch},
|
|
{"po", ctrff::SMDH::Language_Portuguese},
|
|
{"ru", ctrff::SMDH::Language_Russian},
|
|
{"ct", ctrff::SMDH::Language_Chinese_Traditional},
|
|
};
|
|
|
|
void MakeSMDH(const cf7::command::ArgumentList &data) {
|
|
std::string l = cf7::command::GetArg(data, "long");
|
|
std::string s = cf7::command::GetArg(data, "short");
|
|
std::string a = cf7::command::GetArg(data, "author");
|
|
std::string i = cf7::command::GetArg(data, "icon");
|
|
std::string o = cf7::command::GetArg(data, "output");
|
|
if (l.empty() || s.empty() || a.empty() || i.empty() || o.empty()) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("One or more Arguments are not set!",
|
|
cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
ctrff::SMDH smdh = ctrff::SMDH::Default();
|
|
smdh.SetLongTitle(l);
|
|
smdh.SetShortTitle(s);
|
|
smdh.SetAuthor(a);
|
|
std::vector<unsigned char> img;
|
|
int w, h, c;
|
|
ctrff::u8 *buf = stbi_load(i.c_str(), &w, &h, &c, 4);
|
|
if (buf == nullptr) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("Can't open icon File!", cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
if (w != 48 || h != 48) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("Icon is not 48x48 pixels!", cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
img.assign(buf, buf + (w * h * 4));
|
|
smdh.SetIcon(img);
|
|
std::fstream f(o, std::ios::out | std::ios::binary);
|
|
smdh.Write(f);
|
|
cf7::PrintFancy({
|
|
std::make_pair("File Generated", cf7::col(0, 190, 0)),
|
|
});
|
|
}
|
|
|
|
void ReadSMDH(const cf7::command::ArgumentList &data) {
|
|
ctrff::SMDH smdh;
|
|
if (cf7::command::GetArg(data, "input").empty()) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("Input Argument not found!", cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
try {
|
|
smdh.Load(cf7::command::GetArg(data, "input"));
|
|
} catch (const std::exception &e) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair(e.what(), cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
cf7::PrintFancy({
|
|
std::make_pair("CTRFF", cf7::col(220, 160, 0)),
|
|
std::make_pair("SMDH-Parser", cf7::col(240, 200, 0)),
|
|
});
|
|
cf7::PrintFancy({
|
|
std::make_pair("Language", cf7::col(220, 160, 0)),
|
|
std::make_pair("Short", cf7::col(240, 200, 0)),
|
|
std::make_pair("Long", cf7::col(255, 230, 0)),
|
|
std::make_pair("Author", cf7::col(255, 255, 0)),
|
|
});
|
|
for (auto &e : smdh_lang_table) {
|
|
cf7::PrintFancy({
|
|
std::make_pair(" " + e.second, cf7::col(220, 160, 0)),
|
|
std::make_pair(smdh.GetShortTitle(e.first), cf7::col(240, 200, 0)),
|
|
std::make_pair(smdh.GetLongTitle(e.first), cf7::col(255, 230, 0)),
|
|
std::make_pair(smdh.GetAuthor(e.first), cf7::col(255, 255, 0)),
|
|
});
|
|
}
|
|
cf7::PrintFancy({
|
|
std::make_pair("Version", cf7::col(220, 160, 0)),
|
|
std::make_pair(std::to_string(smdh.Version), cf7::col(240, 200, 0)),
|
|
});
|
|
cf7::PrintFancy({
|
|
std::make_pair("Ratings", cf7::col(220, 160, 0)),
|
|
});
|
|
cf7::PrintFancy({
|
|
std::make_pair("Flags", cf7::col(220, 160, 0)),
|
|
});
|
|
for (auto &e : smdh_flag_table) {
|
|
cf7::PrintFancy({
|
|
std::make_pair(" " + e.second, cf7::col(220, 160, 0)),
|
|
std::make_pair(
|
|
std::string((smdh.Settings.Flags & e.first) ? "true" : "false"),
|
|
(smdh.Settings.Flags & e.first) ? cf7::col(0, 190, 0)
|
|
: cf7::col(190, 0, 0)),
|
|
});
|
|
}
|
|
if (smdh.Settings.RegionLock == ctrff::SMDH::Region_FREE) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Region", cf7::col(220, 160, 0)),
|
|
std::make_pair("Free", cf7::col(240, 200, 0)),
|
|
});
|
|
} else {
|
|
for (auto &e : smdh_region_table) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Regions", cf7::col(220, 160, 0)),
|
|
});
|
|
cf7::PrintFancy({
|
|
std::make_pair(e.second, cf7::col(220, 160, 0)),
|
|
std::make_pair(
|
|
std::string(smdh.Settings.RegionLock & e.first ? "true"
|
|
: "false"),
|
|
smdh.Settings.RegionLock & e.first ? cf7::col(0, 190, 0)
|
|
: cf7::col(190, 0, 0)),
|
|
});
|
|
}
|
|
}
|
|
cf7::PrintFancy({
|
|
std::make_pair("MatchmakerID", cf7::col(220, 160, 0)),
|
|
std::make_pair(std::to_string(smdh.Settings.MatchmakerID),
|
|
cf7::col(240, 200, 0)),
|
|
});
|
|
std::string icon_path = cf7::command::GetArg(data, "extract-icon");
|
|
if (!icon_path.empty()) {
|
|
auto icon = smdh.GetIcon();
|
|
stbi_write_png(icon_path.c_str(), 48, 48, 4, icon.data(), 48 * 4);
|
|
/* if (res) {
|
|
// Error
|
|
} else {*/
|
|
cf7::PrintFancy({
|
|
std::make_pair("Export", cf7::col(0, 190, 0)),
|
|
std::make_pair(icon_path, cf7::col(0, 130, 0)),
|
|
std::make_pair("Success", cf7::col(0, 80, 0)),
|
|
});
|
|
// }
|
|
}
|
|
}
|
|
|
|
void Read3DSX(const cf7::command::ArgumentList &data) {
|
|
ctrff::_3dsx _3dsx;
|
|
if (cf7::command::GetArg(data, "input").empty()) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("Input Argument not found!", cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
/*if (!*/ _3dsx.Load(cf7::command::GetArg(data, "input")); /*) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("Could not load 3dsx!", cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}*/
|
|
if (!_3dsx.HasMeta()) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("3dsx has no meta!", cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
ctrff::SMDH smdh = _3dsx.Meta;
|
|
cf7::PrintFancy({
|
|
std::make_pair("CTRFF", cf7::col(220, 160, 0)),
|
|
std::make_pair("SMDH-Parser", cf7::col(240, 200, 0)),
|
|
});
|
|
cf7::PrintFancy({
|
|
std::make_pair("Language", cf7::col(220, 160, 0)),
|
|
std::make_pair("Short", cf7::col(240, 200, 0)),
|
|
std::make_pair("Long", cf7::col(255, 230, 0)),
|
|
std::make_pair("Author", cf7::col(255, 255, 0)),
|
|
});
|
|
for (auto &e : smdh_lang_table) {
|
|
cf7::PrintFancy({
|
|
std::make_pair(" " + e.second, cf7::col(220, 160, 0)),
|
|
std::make_pair(smdh.GetShortTitle(e.first), cf7::col(240, 200, 0)),
|
|
std::make_pair(smdh.GetLongTitle(e.first), cf7::col(255, 230, 0)),
|
|
std::make_pair(smdh.GetAuthor(e.first), cf7::col(255, 255, 0)),
|
|
});
|
|
}
|
|
cf7::PrintFancy({
|
|
std::make_pair("Version", cf7::col(220, 160, 0)),
|
|
std::make_pair(std::to_string(smdh.Version), cf7::col(240, 200, 0)),
|
|
});
|
|
cf7::PrintFancy({
|
|
std::make_pair("Ratings", cf7::col(220, 160, 0)),
|
|
});
|
|
cf7::PrintFancy({
|
|
std::make_pair("Flags", cf7::col(220, 160, 0)),
|
|
});
|
|
for (auto &e : smdh_flag_table) {
|
|
cf7::PrintFancy({
|
|
std::make_pair(" " + e.second, cf7::col(220, 160, 0)),
|
|
std::make_pair(
|
|
std::string((smdh.Settings.Flags & e.first) ? "true" : "false"),
|
|
(smdh.Settings.Flags & e.first) ? cf7::col(0, 190, 0)
|
|
: cf7::col(190, 0, 0)),
|
|
});
|
|
}
|
|
if (smdh.Settings.RegionLock == ctrff::SMDH::Region_FREE) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Region", cf7::col(220, 160, 0)),
|
|
std::make_pair("Free", cf7::col(240, 200, 0)),
|
|
});
|
|
} else {
|
|
for (auto &e : smdh_region_table) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Regions", cf7::col(220, 160, 0)),
|
|
});
|
|
cf7::PrintFancy({
|
|
std::make_pair(e.second, cf7::col(220, 160, 0)),
|
|
std::make_pair(
|
|
std::string(smdh.Settings.RegionLock & e.first ? "true"
|
|
: "false"),
|
|
smdh.Settings.RegionLock & e.first ? cf7::col(0, 190, 0)
|
|
: cf7::col(190, 0, 0)),
|
|
});
|
|
}
|
|
}
|
|
cf7::PrintFancy({
|
|
std::make_pair("MatchmakerID", cf7::col(220, 160, 0)),
|
|
std::make_pair(std::to_string(smdh.Settings.MatchmakerID),
|
|
cf7::col(240, 200, 0)),
|
|
});
|
|
std::string icon_path = cf7::command::GetArg(data, "extract-icon");
|
|
if (!icon_path.empty()) {
|
|
auto icon = smdh.GetIcon();
|
|
stbi_write_png(icon_path.c_str(), 48, 48, 4, icon.data(), 48 * 4);
|
|
/* if (res) {
|
|
// Error
|
|
} else {*/
|
|
cf7::PrintFancy({
|
|
std::make_pair("Export", cf7::col(0, 190, 0)),
|
|
std::make_pair(icon_path, cf7::col(0, 130, 0)),
|
|
std::make_pair("Success", cf7::col(0, 80, 0)),
|
|
});
|
|
// }
|
|
}
|
|
}
|
|
|
|
void Hex(const cf7::command::ArgumentList &data) {
|
|
if (cf7::command::GetArg(data, "input").empty()) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("Input Argument not found!", cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
std::ifstream fr(data[0].second, std::ios::binary);
|
|
if (!fr.is_open()) {
|
|
cf7::PrintFancy({
|
|
std::make_pair("Error", cf7::col(190, 0, 0)),
|
|
std::make_pair("Failed to open Input File!", cf7::col(130, 0, 0)),
|
|
});
|
|
return;
|
|
}
|
|
std::vector<unsigned char> buf(std::istreambuf_iterator<char>(fr), {});
|
|
fr.close();
|
|
cf7::PrintFancy({
|
|
std::make_pair("CTRFF HEXDUMP", cf7::col(255, 165, 0)),
|
|
std::make_pair(data[0].second, cf7::col(255, 210, 0)),
|
|
std::make_pair(FormatBytes(buf.size()), cf7::col(255, 255, 0)),
|
|
});
|
|
std::cout << "+----------+-------------------------------------------------+-"
|
|
"-----------------+"
|
|
<< std::endl;
|
|
std::cout << "| Adress | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | "
|
|
"ASCII |"
|
|
<< std::endl;
|
|
std::cout << "+----------+-------------------------------------------------+-"
|
|
"-----------------+"
|
|
<< std::endl;
|
|
std::cout << "| " << std::hex << std::setw(8) << std::setfill('0')
|
|
<< (unsigned int)0 << " | ";
|
|
std::vector<char> ascii;
|
|
int lidx = 0;
|
|
for (size_t i = 0; i < buf.size(); i++) {
|
|
lidx++;
|
|
ascii.push_back((char)buf[i]);
|
|
std::cout << std::hex << std::setw(2) << std::setfill('0') << std::uppercase
|
|
<< (int)buf[i] << " ";
|
|
if (((i + 1) % 0x10) == 0 && i > 14) {
|
|
std::cout << "| ";
|
|
for (auto &it : ascii)
|
|
std::cout << std::dec
|
|
<< (((int)it >= 32) && ((int)it <= 126) ? it : '.');
|
|
ascii.clear();
|
|
std::cout << " |" << std::endl;
|
|
std::cout << "| " << std::hex << std::setw(8) << std::setfill('0')
|
|
<< (unsigned int)i + 1 << " | ";
|
|
lidx = 0;
|
|
}
|
|
}
|
|
if (lidx < 16) {
|
|
for (int i = lidx; i < 16; i++) {
|
|
ascii.push_back('X');
|
|
std::cout << "XX ";
|
|
if (i == 15) {
|
|
std::cout << "| ";
|
|
for (auto &it : ascii)
|
|
std::cout << std::dec
|
|
<< (((int)it >= 32) && ((int)it <= 126) ? it : '.');
|
|
ascii.clear();
|
|
std::cout << " |" << std::endl;
|
|
}
|
|
}
|
|
std::cout
|
|
<< "+----------+-------------------------------------------------+-"
|
|
"-----------------+"
|
|
<< std::endl;
|
|
}
|
|
}
|
|
|
|
void LZ11Compress(const cf7::command::ArgumentList &data) {
|
|
std::string i = cf7::command::GetArg(data, "input");
|
|
std::string o = cf7::command::GetArg(data, "output");
|
|
std::fstream in(i, std::ios::in | std::ios::binary);
|
|
in.seekg(0, std::ios::end);
|
|
size_t s = in.tellg();
|
|
in.seekg(0, std::ios::beg);
|
|
std::vector<unsigned char> buf(s);
|
|
in.read(reinterpret_cast<char *>(buf.data()), s);
|
|
in.close();
|
|
cf7::PrintFancy({
|
|
std::make_pair("Input", cf7::col(255, 165, 0)),
|
|
std::make_pair(i, cf7::col(255, 210, 0)),
|
|
std::make_pair(FormatBytes(buf.size()), cf7::col(255, 255, 0)),
|
|
});
|
|
auto res = ctrff::LZ11::Compress(buf);
|
|
cf7::PrintFancy({
|
|
std::make_pair("Output", cf7::col(255, 165, 0)),
|
|
std::make_pair(o, cf7::col(255, 210, 0)),
|
|
std::make_pair(FormatBytes(res.size()), cf7::col(255, 255, 0)),
|
|
});
|
|
std::fstream out(o, std::ios::out | std::ios::binary);
|
|
out.write(reinterpret_cast<const char *>(res.data()), res.size());
|
|
out.close();
|
|
}
|
|
|
|
void BCLIMMaker(const cf7::command::ArgumentList &data) {
|
|
std::string i = cf7::command::GetArg(data, "input");
|
|
std::string o = cf7::command::GetArg(data, "output");
|
|
std::string f = cf7::command::GetArg(data, "format");
|
|
if (i.empty() || o.empty()) {
|
|
std::cout << "[ctrff] BCLIM: Error, no input or output" << std::endl;
|
|
return;
|
|
}
|
|
if (f.empty() || (f.compare("rgba32") != 0 && f.compare("a8") != 0 &&
|
|
f.compare("rgb565") != 0)) {
|
|
f = "a8";
|
|
}
|
|
int w = 0, h = 0, c = 0;
|
|
auto ret = stbi_load(i.c_str(), &w, &h, &c, 4);
|
|
if (!ret) {
|
|
std::cout << "[ctrff] BCLIM: Failed to load image " + i << std::endl;
|
|
return;
|
|
}
|
|
if (!PD::BitUtil::IsSingleBit(w) || !PD::BitUtil::IsSingleBit(h)) {
|
|
std::cout << "[ctrff] BCLIM: Image with and height must be a power of 8!";
|
|
return;
|
|
}
|
|
size_t size = w * h;
|
|
if (f == "rgba32") {
|
|
size *= 4;
|
|
} else if (f == "rgb565") {
|
|
size *= 2;
|
|
}
|
|
std::vector<ctrff::u8> res(size);
|
|
if (f == "rgba32" || f == "a8") {
|
|
for (int x = 0; x < w; x++) {
|
|
for (int y = 0; y < h; y++) {
|
|
int src = (y * w + x) * 4;
|
|
int dst = ctrff::TileIndex(x, y, w);
|
|
if (f == "rgba32") {
|
|
dst *= 4;
|
|
res[dst + 3] = ret[src + 0];
|
|
res[dst + 2] = ret[src + 1];
|
|
res[dst + 1] = ret[src + 2];
|
|
res[dst + 0] = ret[src + 3];
|
|
} else {
|
|
res[dst] = ret[src + 3];
|
|
}
|
|
}
|
|
}
|
|
} else if (f == "rgb565") {
|
|
std::vector<ctrff::u16> res16(w * h);
|
|
ctrff::RGBA2RGB565(res16.data(),
|
|
std::vector<ctrff::u8>(ret, ret + (w * h * 4)), w, h);
|
|
for (int i = 0; i < res16.size(); i++) {
|
|
int pos = i * 2;
|
|
res[pos] = (ctrff::u8)(res16[i] & 0xff);
|
|
res[pos + 1] = (ctrff::u8)((res16[i] >> 8) & 0xff);
|
|
}
|
|
}
|
|
ctrff::BCLIM file;
|
|
ctrff::BCLIM::Format fmt = ctrff::BCLIM::A8;
|
|
if (f == "rgba32") {
|
|
fmt = ctrff::BCLIM::RGBA8888;
|
|
} else if (f == "rgb565") {
|
|
fmt = ctrff::BCLIM::RGB565;
|
|
}
|
|
file.CreateByImage(res, w, h, fmt);
|
|
file.Save(o);
|
|
std::cout << "File " + o + " created" << std::endl;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
cf7::fancy_print = false;
|
|
cf7::colors_supported = false;
|
|
cf7::arg_mgr mgr(argc, argv);
|
|
mgr.SetAppInfo("ctrff", "1.0.0");
|
|
auto makesmdh_cmd = cf7::command("makesmdh", "Create a SMDH File");
|
|
makesmdh_cmd.AddSubEntry(
|
|
cf7::command::sub("i", "icon", "Icon file path (48x48)", true));
|
|
makesmdh_cmd.AddSubEntry(
|
|
cf7::command::sub("o", "output", "Output smdh path", true));
|
|
for (auto &it : smdh_lang_stropts) {
|
|
if (it.first.empty()) {
|
|
makesmdh_cmd.AddSubEntry(cf7::command::sub(
|
|
"s", "short", "Short Title (All Languages)", false));
|
|
makesmdh_cmd.AddSubEntry(
|
|
cf7::command::sub("l", "long", "Long Title (All Languages)", false));
|
|
makesmdh_cmd.AddSubEntry(
|
|
cf7::command::sub("a", "author", "Author (All Languages)", false));
|
|
} else {
|
|
makesmdh_cmd.AddSubEntry(cf7::command::sub(
|
|
"s-" + it.first, "short-" + it.first,
|
|
"Short Title " + smdh_lang_table.at(it.second), false));
|
|
makesmdh_cmd.AddSubEntry(cf7::command::sub(
|
|
"l-" + it.first, "long-" + it.first,
|
|
"Long Title " + smdh_lang_table.at(it.second), false));
|
|
makesmdh_cmd.AddSubEntry(
|
|
cf7::command::sub("a-" + it.first, "author-" + it.first,
|
|
"Author " + smdh_lang_table.at(it.second), false));
|
|
}
|
|
}
|
|
makesmdh_cmd.SetFunction(MakeSMDH);
|
|
mgr.AddCommand(makesmdh_cmd);
|
|
mgr.AddCommand(
|
|
cf7::command("readsmdh", "Reads a smdh file and can extract icon")
|
|
.AddSubEntry(
|
|
cf7::command::sub("i", "input", "Input smdh path!", true))
|
|
.AddSubEntry(cf7::command::sub("e", "extract-icon",
|
|
"Path to Extract Icon to", false))
|
|
.SetFunction(ReadSMDH));
|
|
mgr.AddCommand(cf7::command("read3dsx", "Read Data of a 3dsx file")
|
|
.AddSubEntry(cf7::command::sub("i", "input",
|
|
"Input 3dsx path!", true))
|
|
.AddSubEntry(cf7::command::sub("e", "extract-icon",
|
|
"Output icon path!", false))
|
|
.SetFunction(Read3DSX));
|
|
mgr.AddCommand(
|
|
cf7::command("lz11", "Creates a LZ11 Compressed File")
|
|
.AddSubEntry(cf7::command::sub("i", "input", "Input file path", true))
|
|
.AddSubEntry(
|
|
cf7::command::sub("o", "output", "Output file path", true))
|
|
.SetFunction(LZ11Compress));
|
|
mgr.AddCommand(
|
|
cf7::command("hex", "Show Hex view of a File")
|
|
.AddSubEntry(cf7::command::sub("i", "input", "Input File path", true))
|
|
.SetFunction(Hex));
|
|
mgr.AddCommand(
|
|
cf7::command("makebclim", "Create CTR Layout Image")
|
|
.AddSubEntry(cf7::command::sub("i", "input", "Input png|bmp", true))
|
|
.AddSubEntry(cf7::command::sub("o", "output",
|
|
"Output path of .bclim file", true))
|
|
.AddSubEntry(cf7::command::sub("f", "format",
|
|
"Image format rgba32|rgb565|a8", true))
|
|
.SetFunction(BCLIMMaker));
|
|
mgr.Execute();
|
|
return 0;
|
|
} |