# Rewrite Stage 1
- Switch to CMake build system - delete everything for a new structure - Add SmartCtor class and saperate New func - New Faster and Open Lithium Command API - Rewritten Text Renderer to ghet rid of all that janky code - New TimeTrace System and use of NanoTime using GetTimeNano - Overall going to a more Object oriented way - Updated vec api to support vec2 input on vec3 ## Todo - Support vec2 and vec3 in vec4 as inputs - Continue UI7 - Fix SystemFont on 3ds freezing the system - Fix TTF Font UV Mapping ## Warning Creating Apps for the 3ds is not possible yet as the 3ds is Freezing and this is only stage 1 of ? Emulator works perfect
This commit is contained in:
@ -1,59 +0,0 @@
|
||||
#include <3ds.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <pd/Error.hpp>
|
||||
#include <pd/UI7.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
#include <pd/palladium.hpp>
|
||||
|
||||
void pdi_save_report(const std::string& msg) {
|
||||
auto ts = Palladium::GetTimeStr();
|
||||
std::ofstream f("sdmc:/Palladium/Reports/report_" + ts + ".txt");
|
||||
f << "Palladium Error [" << pdi_app_name << ", " << ts << "]" << std::endl;
|
||||
f << "Error Message: " << std::endl;
|
||||
f << msg << std::endl;
|
||||
f << "SysInfo: " << std::endl;
|
||||
f << "- Citra -> " << (pdi_is_citra ? "true" : "false") << std::endl;
|
||||
f.close();
|
||||
}
|
||||
|
||||
namespace Palladium {
|
||||
void Error(const std::string& msg) {
|
||||
pdi_save_report(msg);
|
||||
if (pdi_graphics_on) {
|
||||
while (aptMainLoop()) {
|
||||
hidScanInput();
|
||||
if (hidKeysDown() & KEY_START) break;
|
||||
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
||||
C3D_RenderTargetClear(pd_top, C3D_CLEAR_ALL, 0x00000000, 0);
|
||||
C3D_RenderTargetClear(pd_top_right, C3D_CLEAR_ALL, 0x00000000, 0);
|
||||
C3D_RenderTargetClear(pd_bottom, C3D_CLEAR_ALL, 0x00000000, 0);
|
||||
Palladium::LI::OnScreen(false);
|
||||
if (UI7::BeginMenu("Palladium - Error Manager", NVec2(),
|
||||
UI7MenuFlags_TitleMid)) {
|
||||
UI7::Label(msg);
|
||||
UI7::Label("Press Start to Exit!");
|
||||
UI7::EndMenu();
|
||||
}
|
||||
Palladium::LI::OnScreen(true);
|
||||
UI7::Update();
|
||||
Palladium::LI::Render(pd_top, pd_bottom);
|
||||
C3D_FrameEnd(0);
|
||||
}
|
||||
exit(0);
|
||||
} else {
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_TOP, NULL);
|
||||
printf("Palladium - ERROR MANAGER\n\n%s\n", msg.c_str());
|
||||
printf("Report Saved in\nsdmc:/Palladium/Reports\n");
|
||||
printf("Press Start to Exit\n");
|
||||
while (aptMainLoop()) {
|
||||
hidScanInput();
|
||||
if (hidKeysDown() & KEY_START) break;
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
gfxExit();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
} // namespace Palladium
|
@ -1,47 +0,0 @@
|
||||
#include <pd/Hardware.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
|
||||
// Os Specific includes
|
||||
#include <3ds.h>
|
||||
|
||||
void Palladium::Hardware::Initialisize() {
|
||||
mcuHwcInit();
|
||||
atexit(mcuHwcExit);
|
||||
ptmuInit();
|
||||
atexit(ptmuExit);
|
||||
}
|
||||
|
||||
bool Palladium::Hardware::IsHeadphones() {
|
||||
if (pdi_is_ndsp) {
|
||||
bool inserted;
|
||||
DSP_GetHeadphoneStatus(&inserted);
|
||||
return inserted;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Palladium::Hardware::IsCharging() {
|
||||
uint8_t var;
|
||||
PTMU_GetBatteryChargeState(&var);
|
||||
// Some Security Stuff
|
||||
if (var < 0x00 && var > 0x01) {
|
||||
return false;
|
||||
}
|
||||
return (var == 0x01 ? true : false);
|
||||
}
|
||||
|
||||
int Palladium::Hardware::GetBatteryPercentage() {
|
||||
uint8_t percentLevel = 0;
|
||||
MCUHWC_GetBatteryLevel(&percentLevel);
|
||||
return percentLevel;
|
||||
}
|
||||
|
||||
float Palladium::Hardware::Get3dSliderLevel() { return osGet3DSliderState(); }
|
||||
|
||||
float Palladium::Hardware::GetSoundSliderLevel() {
|
||||
uint8_t percentLevel;
|
||||
MCUHWC_GetSoundSliderLevel(&percentLevel);
|
||||
return (float)percentLevel / 100;
|
||||
}
|
||||
|
||||
int Palladium::Hardware::GetWifiLevel() { return osGetWifiStrength(); }
|
118
source/Hid.cpp
118
source/Hid.cpp
@ -1,118 +0,0 @@
|
||||
#include <map>
|
||||
#include <pd/Hid.hpp>
|
||||
|
||||
namespace Palladium {
|
||||
class HidApi {
|
||||
public:
|
||||
HidApi() {}
|
||||
~HidApi() {}
|
||||
|
||||
void setKdown(uint32_t &in) { actions[Hid::Down] = ∈ }
|
||||
void setKheld(uint32_t &in) { actions[Hid::Held] = ∈ }
|
||||
void setKup(uint32_t &in) { actions[Hid::Up] = ∈ }
|
||||
void setKrepeat(uint32_t &in) { actions[Hid::DownRepeat] = ∈ }
|
||||
void setTouchCoords(NVec2 &touch_coords) { touch_pos = &touch_coords; }
|
||||
void setJS1Movement(NVec2 &mvmt) { js1_mv = &mvmt; }
|
||||
void setJS2Movement(NVec2 &mvmt) { js2_mv = &mvmt; }
|
||||
void bindKey(const std::string &event, uint32_t key) {
|
||||
key_bindings[event] = key; // Overrides if existing
|
||||
}
|
||||
void lock(bool lock) { locked = lock; }
|
||||
|
||||
void clear() {
|
||||
// Clears Functionality for 1 Frame
|
||||
last_touch_pos = NVec2();
|
||||
touch_pos[0] = NVec2();
|
||||
dtp = NVec2();
|
||||
backups[Hid::Down] = 0;
|
||||
backups[Hid::Held] = 0;
|
||||
backups[Hid::Up] = 0;
|
||||
backups[Hid::DownRepeat] = 0;
|
||||
}
|
||||
|
||||
bool isEvent(const std::string &event, Hid::Actions action) {
|
||||
if (locked) return false;
|
||||
if (key_bindings.find(event) == key_bindings.end())
|
||||
return false; // Unknown Event
|
||||
if (backups.find(action) == backups.end())
|
||||
return false; // What? NOT Alowed acrion
|
||||
if (backups[action] & key_bindings[event])
|
||||
return true; // Action contains key as flag
|
||||
return false; // Nothing to do
|
||||
}
|
||||
|
||||
NVec2 getTouchPos() { return touch_pos[0]; }
|
||||
NVec2 getLastTouchPos() { return last_touch_pos; }
|
||||
NVec2 getTouchDownPos() { return dtp; }
|
||||
|
||||
void update() {
|
||||
last_touch_pos = touch_pos[0];
|
||||
if (isEvent("touch", Hid::Down)) {
|
||||
dtp = touch_pos[0];
|
||||
}
|
||||
if (isEvent("touch", Hid::Up)) {
|
||||
dtp = NVec2();
|
||||
}
|
||||
for (const auto &it : actions) {
|
||||
backups[it.first] = it.second[0];
|
||||
}
|
||||
if (locked) {
|
||||
actions[Hid::Down][0] = 0;
|
||||
actions[Hid::Held][0] = 0;
|
||||
actions[Hid::Up][0] = 0;
|
||||
actions[Hid::DownRepeat][0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<Hid::Actions, uint32_t *> actions;
|
||||
std::map<Hid::Actions, uint32_t> backups;
|
||||
NVec2 *touch_pos = nullptr;
|
||||
NVec2 *js1_mv = nullptr;
|
||||
NVec2 *js2_mv = nullptr;
|
||||
|
||||
NVec2 last_touch_pos;
|
||||
NVec2 dtp;
|
||||
|
||||
std::map<std::string, uint32_t> key_bindings;
|
||||
bool locked = false;
|
||||
};
|
||||
static HidApi hid_handler;
|
||||
namespace Hid {
|
||||
// Register Functions
|
||||
// Register Current state values
|
||||
void RegKeyDown(uint32_t &key_down) { hid_handler.setKdown(key_down); }
|
||||
|
||||
void RegKeyHeld(uint32_t &key_held) { hid_handler.setKheld(key_held); }
|
||||
|
||||
void RegKeyUp(uint32_t &key_up) { hid_handler.setKup(key_up); }
|
||||
|
||||
void RegKeyRepeat(uint32_t &repeat) { hid_handler.setKrepeat(repeat); }
|
||||
|
||||
void RegTouchCoords(NVec2 &touch_pos) { hid_handler.setTouchCoords(touch_pos); }
|
||||
|
||||
void RegAnalog1Movement(NVec2 &movement) {
|
||||
hid_handler.setJS1Movement(movement);
|
||||
}
|
||||
|
||||
void RegAnalog2Movement(NVec2 &movement) {
|
||||
hid_handler.setJS2Movement(movement);
|
||||
}
|
||||
|
||||
// Register Keys
|
||||
void RegKeyEvent(const std::string &event, uint32_t key) {
|
||||
hid_handler.bindKey(event, key);
|
||||
}
|
||||
|
||||
bool IsEvent(const std::string &event, Actions action) {
|
||||
return hid_handler.isEvent(event, action);
|
||||
}
|
||||
NVec2 GetTouchPosition() { return hid_handler.getTouchPos(); }
|
||||
NVec2 GetLastTouchPosition() { return hid_handler.getLastTouchPos(); }
|
||||
NVec2 GetTouchDownPosition() { return hid_handler.getTouchDownPos(); }
|
||||
void Update() { hid_handler.update(); }
|
||||
void Lock() { hid_handler.lock(true); }
|
||||
void Unlock() { hid_handler.lock(false); }
|
||||
void Clear() { hid_handler.clear(); }
|
||||
} // namespace Hid
|
||||
} // namespace Palladium
|
@ -1,44 +0,0 @@
|
||||
#include <pd/external/stb_image.h>
|
||||
|
||||
#include <pd/Image.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Palladium {
|
||||
|
||||
void Image::Load(const std::string &path) {
|
||||
// Make sure to cleanup
|
||||
Delete();
|
||||
if (!img) img = Texture::New();
|
||||
img->LoadFile(path);
|
||||
}
|
||||
|
||||
void Image::From_NIMG(const nimg &image) {
|
||||
// Make sure to cleanup
|
||||
Delete();
|
||||
if (!img) img = Texture::New();
|
||||
img->LoadPixels(image.pixel_buffer, image.width, image.height);
|
||||
}
|
||||
|
||||
Texture::Ref Image::Get() {
|
||||
if (!Loadet()) {
|
||||
return nullptr;
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
void Image::Set(Texture::Ref i, NVec4 uvs) {
|
||||
Delete();
|
||||
if (uvs.x() != -1) custom_uvs = uvs;
|
||||
img = i;
|
||||
}
|
||||
|
||||
NVec2 Image::GetSize() {
|
||||
if (!img) return NVec2(0, 0);
|
||||
return img->GetSize();
|
||||
}
|
||||
|
||||
void Image::Delete() { img = nullptr; }
|
||||
|
||||
bool Image::Loadet() { return img != nullptr; }
|
||||
} // namespace Palladium
|
@ -1,149 +0,0 @@
|
||||
#include <3ds.h>
|
||||
|
||||
#include <pd/Installer.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
|
||||
namespace Palladium {
|
||||
Result DeletePrevious(u64 id, FS_MediaType mt) {
|
||||
if (!pdi_is_am_init) return -1;
|
||||
u32 num_titles = 0;
|
||||
Result ret = AM_GetTitleCount(mt, &num_titles);
|
||||
if (R_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 read_titles = 0;
|
||||
auto ids = new u64[num_titles];
|
||||
ret = AM_GetTitleList(&read_titles, mt, num_titles, ids);
|
||||
|
||||
if (R_FAILED(ret)) {
|
||||
delete[] ids;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < read_titles; i++) {
|
||||
if (ids[i] == id) {
|
||||
ret = AM_DeleteAppTitle(mt, id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] ids;
|
||||
if (R_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FS_MediaType GetTitleDest(u64 id) {
|
||||
u16 platform = (u16)((id >> 48) & 0xFFFF);
|
||||
u16 category = (u16)((id >> 32) & 0xFFFF);
|
||||
u8 variation = (u8)(id & 0xFF);
|
||||
|
||||
/* DSiWare 3DS DSiWare, System, DLP
|
||||
* Application System Title */
|
||||
return platform == 0x0003 || (platform == 0x0004 &&
|
||||
((category & 0x8011) != 0 ||
|
||||
(category == 0x0000 && variation == 0x02)))
|
||||
? MEDIATYPE_NAND
|
||||
: MEDIATYPE_SD;
|
||||
}
|
||||
|
||||
InstallerInfo pdi_installer_info;
|
||||
|
||||
InstallerInfo InstallGetInfo() { return pdi_installer_info; }
|
||||
|
||||
void InstallSetBuffersSize(unsigned int bytes) {
|
||||
if (pdi_installer_info.active) return;
|
||||
if (bytes == 0) return;
|
||||
if (bytes >= 0x200000) bytes = 0x200000;
|
||||
pdi_installer_info.mem_size = bytes;
|
||||
}
|
||||
|
||||
Result InstallCia(const std::string& path, bool self) {
|
||||
if (!pdi_is_am_init) return -1;
|
||||
if (pdi_installer_info.active) return -1;
|
||||
u32 bytes_read = 0;
|
||||
u32 bytes_written = 0;
|
||||
pdi_installer_info.current = 0;
|
||||
// Set 1 to avoid div0 error
|
||||
pdi_installer_info.total = 1;
|
||||
u64 size = 0;
|
||||
Handle cia, file;
|
||||
AM_TitleEntry info;
|
||||
Result ret = 0;
|
||||
FS_MediaType media = MEDIATYPE_SD;
|
||||
|
||||
std::string pth;
|
||||
if (path[0] == '/') {
|
||||
pth = path;
|
||||
} else if (path.substr(0, 5) == "sdmc:") {
|
||||
pth = path.substr(5);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""),
|
||||
fsMakePath(PATH_ASCII, pth.c_str()),
|
||||
FS_OPEN_READ, 0);
|
||||
|
||||
if (R_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = AM_GetCiaFileInfo(media, &info, file);
|
||||
|
||||
if (R_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
media = GetTitleDest(info.titleID);
|
||||
|
||||
if (!self) {
|
||||
ret = DeletePrevious(info.titleID, media);
|
||||
if (R_FAILED(ret)) return ret;
|
||||
}
|
||||
|
||||
ret = FSFILE_GetSize(file, &size);
|
||||
|
||||
if (R_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = AM_StartCiaInstall(media, &cia);
|
||||
|
||||
if (R_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> buf(pdi_installer_info.mem_size);
|
||||
pdi_installer_info.total = size;
|
||||
|
||||
do {
|
||||
FSFILE_Read(file, &bytes_read, pdi_installer_info.current, &buf[0],
|
||||
buf.size());
|
||||
FSFILE_Write(cia, &bytes_written, pdi_installer_info.current, &buf[0],
|
||||
buf.size(), FS_WRITE_FLUSH);
|
||||
pdi_installer_info.current += bytes_read;
|
||||
} while (pdi_installer_info.current < pdi_installer_info.total);
|
||||
|
||||
ret = AM_FinishCiaInstall(cia);
|
||||
|
||||
if (R_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = FSFILE_Close(file);
|
||||
|
||||
if (R_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (self) {
|
||||
aptSetChainloaderToSelf();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace Palladium
|
@ -1,789 +0,0 @@
|
||||
#include <pd/external/stb_truetype.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <codecvt>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <pd/Lithium.hpp>
|
||||
#include <pd/base/Color.hpp>
|
||||
#include <pd/li7_shader.hpp>
|
||||
#include <pd/palladium.hpp>
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
std::wstring make_wstring(const std::string& str) {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
|
||||
return converter.from_bytes(str);
|
||||
}
|
||||
|
||||
namespace Palladium {
|
||||
PDLithiumFlags LI::flags = PDLithiumFlags_Default;
|
||||
const float LI::default_font_size = 24.f;
|
||||
const float LI::default_text_size = 0.7f;
|
||||
float LI::text_scale = 0.7f;
|
||||
// Renderer Stuff
|
||||
bool LI::bottom_screen = false;
|
||||
NVec2 LI::screen_size;
|
||||
int LI::layer = 0;
|
||||
std::vector<LI::Cmd> LI::draw_lists[2];
|
||||
Texture::Ref LI::active_texture;
|
||||
Texture::Ref LI::single_color;
|
||||
std::vector<LI::Vtx, LinearAllocator<LI::Vtx>> LI::vertex_buffer;
|
||||
std::vector<unsigned short, LinearAllocator<unsigned short>> LI::idx_buffer;
|
||||
size_t LI::vertex_index = 0;
|
||||
size_t LI::idx_index = 0;
|
||||
bool LI::font_update = false;
|
||||
LIFont::Ref LI::font;
|
||||
bool LI::sysfont_render = false;
|
||||
std::map<std::string, LI::TextBox> LI::text_sizes;
|
||||
int LI::cmd_index = 0;
|
||||
// Debug
|
||||
int LI::num_vertices = 0;
|
||||
int LI::num_drawcalls = 0;
|
||||
int LI::num_commands = 0;
|
||||
int LI::num_indices = 0;
|
||||
// Shader
|
||||
DVLB_s* LI::li7_dvlb;
|
||||
shaderProgram_s LI::li7_prog;
|
||||
C3D_AttrInfo LI::li7_attr;
|
||||
int LI::uLoc_proj;
|
||||
|
||||
void LIFont::LoadTFF(const std::string path, int px_size) {
|
||||
sysfnt = false;
|
||||
Palladium::Ftrace::ScopedTrace st(
|
||||
"LIFont", std::filesystem::path(path).filename().string());
|
||||
this->pixel_height = px_size;
|
||||
if (!Palladium::FS::FileExist(path)) return;
|
||||
int type = px_size * 16;
|
||||
// Load TTF
|
||||
stbtt_fontinfo inf;
|
||||
std::ifstream loader(path, std::ios::binary);
|
||||
if (!loader.is_open()) return;
|
||||
loader.seekg(0, std::ios::end);
|
||||
size_t len = loader.tellg();
|
||||
loader.seekg(0, std::ios::beg);
|
||||
unsigned char* buffer = new unsigned char[len];
|
||||
loader.read(reinterpret_cast<char*>(buffer), len);
|
||||
loader.close();
|
||||
stbtt_InitFont(&inf, buffer, 0);
|
||||
std::vector<unsigned char> fmap(type * type * 4);
|
||||
float scale = stbtt_ScaleForPixelHeight(&inf, pixel_height);
|
||||
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
|
||||
int baseline = static_cast<int>(ascent * scale);
|
||||
|
||||
name = path;
|
||||
auto ftex = Texture::New();
|
||||
NVec2 offset;
|
||||
for (int c = 0; c < 255; c++) {
|
||||
CPI codepoint;
|
||||
if (stbtt_IsGlyphEmpty(&inf, c)) {
|
||||
codepoint.codepoint = c;
|
||||
codepoint.tex = ftex;
|
||||
codepoint.invalid = true;
|
||||
cpmap[c] = codepoint;
|
||||
continue;
|
||||
}
|
||||
|
||||
int width, height, xOffset, yOffset;
|
||||
unsigned char* bitmap = stbtt_GetCodepointBitmap(
|
||||
&inf, scale, scale, c, &width, &height, &xOffset, &yOffset);
|
||||
int x0, y0, x1, y1;
|
||||
stbtt_GetCodepointBitmapBox(&inf, c, scale, scale, &x0, &y0, &x1, &y1);
|
||||
|
||||
if (offset[0] + width > type) {
|
||||
offset[1] += pixel_height;
|
||||
offset[0] = 0;
|
||||
}
|
||||
|
||||
codepoint.uv[0] = static_cast<float>((float)offset[0] / (float)type);
|
||||
codepoint.uv[1] = 1.0f - static_cast<float>((float)offset[1] / (float)type);
|
||||
codepoint.uv[2] =
|
||||
static_cast<float>(float(offset[0] + width) / (float)type);
|
||||
codepoint.uv[3] =
|
||||
1.0f - static_cast<float>(float(offset[1] + height) / (float)type);
|
||||
|
||||
codepoint.tex = ftex;
|
||||
codepoint.szs[0] = width;
|
||||
codepoint.szs[1] = height;
|
||||
codepoint.off = baseline + yOffset;
|
||||
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
int map_pos = ((offset[1] + y) * type + (offset[0] + x)) * 4;
|
||||
|
||||
fmap[map_pos + 0] = 255;
|
||||
fmap[map_pos + 1] = 255;
|
||||
fmap[map_pos + 2] = 255;
|
||||
fmap[map_pos + 3] = bitmap[x + y * width];
|
||||
}
|
||||
}
|
||||
offset[0] += width;
|
||||
if (offset[0] + width > type) {
|
||||
offset[1] += pixel_height;
|
||||
offset[0] = 0;
|
||||
}
|
||||
free(bitmap);
|
||||
cpmap[c] = codepoint;
|
||||
}
|
||||
ftex->LoadPixels(fmap, type, type, Palladium::Texture::RGBA32,
|
||||
Palladium::Texture::LINEAR);
|
||||
this->tex.push_back(ftex);
|
||||
}
|
||||
|
||||
void LIFont::LoadBitmapFont(const std::string& path) {}
|
||||
|
||||
void LIFont::LoadSystemFont() {
|
||||
Palladium::Ftrace::ScopedTrace st("li", "sysfnt");
|
||||
sysfnt = true;
|
||||
name = "System Font";
|
||||
// Code to Load the System Font
|
||||
const auto fnt = fontGetSystemFont();
|
||||
const auto fnt_info = fontGetInfo(fnt);
|
||||
const auto glyph_info = fontGetGlyphInfo(fnt);
|
||||
this->tex.resize(glyph_info->nSheets + 1);
|
||||
pixel_height = glyph_info->cellHeight;
|
||||
for (size_t i = 0; i < glyph_info->nSheets; i++) {
|
||||
auto stex = Texture::New();
|
||||
auto tx = new C3D_Tex;
|
||||
tx->data = fontGetGlyphSheetTex(fnt, i);
|
||||
tx->fmt = (GPU_TEXCOLOR)glyph_info->sheetFmt;
|
||||
tx->size = glyph_info->sheetSize;
|
||||
tx->width = glyph_info->sheetWidth;
|
||||
tx->height = glyph_info->sheetHeight;
|
||||
tx->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) |
|
||||
GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
|
||||
GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT);
|
||||
tx->border = 0xffffffff;
|
||||
tx->lodParam = 0;
|
||||
stex->ExternalLoad(tx, NVec2(tx->width, tx->height), NVec4(0, 1, 1, 0));
|
||||
tex[i] = stex;
|
||||
}
|
||||
std::vector<unsigned int> charSet;
|
||||
for (auto cmap = fnt_info->cmap; cmap; cmap = cmap->next) {
|
||||
if (cmap->mappingMethod == CMAP_TYPE_DIRECT) {
|
||||
if (cmap->codeEnd >= cmap->codeBegin) {
|
||||
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
|
||||
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
|
||||
if (cmap->indexOffset + (i - cmap->codeBegin) == 0xFFFF) break;
|
||||
charSet.emplace_back(i);
|
||||
}
|
||||
}
|
||||
} else if (cmap->mappingMethod == CMAP_TYPE_TABLE) {
|
||||
if (cmap->codeEnd >= cmap->codeBegin) {
|
||||
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
|
||||
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
|
||||
if (cmap->indexTable[i - cmap->codeBegin] == 0xFFFF) continue;
|
||||
charSet.emplace_back(i);
|
||||
}
|
||||
}
|
||||
} else if (cmap->mappingMethod == CMAP_TYPE_SCAN) {
|
||||
charSet.reserve(charSet.size() + cmap->nScanEntries);
|
||||
for (unsigned i = 0; i < cmap->nScanEntries; ++i) {
|
||||
if (cmap->scanEntries[i].code >= cmap->codeBegin &&
|
||||
cmap->scanEntries[i].code <= cmap->codeEnd) {
|
||||
if (cmap->scanEntries[i].glyphIndex != 0xFFFF) {
|
||||
charSet.emplace_back(cmap->scanEntries[i].code);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(charSet.begin(), charSet.end());
|
||||
charSet.erase(std::unique(charSet.begin(), charSet.end()));
|
||||
|
||||
for (auto cp : charSet) {
|
||||
int gidx = fontGlyphIndexFromCodePoint(fnt, cp);
|
||||
if (gidx >= 0xFFFF) continue;
|
||||
CPI codepoint;
|
||||
fontGlyphPos_s dat;
|
||||
fontCalcGlyphPos(&dat, fnt, gidx, GLYPH_POS_CALC_VTXCOORD, 1.f, 1.f);
|
||||
|
||||
codepoint.codepoint = cp;
|
||||
codepoint.uv[0] = dat.texcoord.left;
|
||||
codepoint.uv[1] = dat.texcoord.top;
|
||||
codepoint.uv[2] = dat.texcoord.right;
|
||||
codepoint.uv[3] = dat.texcoord.bottom;
|
||||
if (tex.at(dat.sheetIndex) != nullptr) codepoint.tex = tex[dat.sheetIndex];
|
||||
codepoint.szs[0] = dat.vtxcoord.right;
|
||||
codepoint.szs[1] = dat.vtxcoord.bottom;
|
||||
codepoint.off = 0;
|
||||
cpmap[cp] = codepoint;
|
||||
}
|
||||
}
|
||||
|
||||
int LIFont::GetPixelHeight() { return this->pixel_height; }
|
||||
|
||||
LIFont::CPI LIFont::GetCodepoint(unsigned int c) {
|
||||
auto res = cpmap.find(c);
|
||||
if (res == cpmap.end()) return CPI(true);
|
||||
return res->second;
|
||||
}
|
||||
|
||||
void LIFont::Dump() {
|
||||
// std::ofstream ofs("sdmc:/font.txt", std::ios::out);
|
||||
// ofs << "LI7 Font Dump" << std::endl;
|
||||
// ofs << "Pixel Height: " << (int)pixel_height << std::endl;
|
||||
// for (auto& it : this->cpmap) {
|
||||
// ofs << " Codepoint: " << (int)it.codepoint << std::endl;
|
||||
// ofs << " Tex: " << (unsigned int)it.tex->Get() << std::endl;
|
||||
// ofs << " Szs: (" << (int)it.szs[0] << ", " << (int)it.szs[1] << ")"
|
||||
// << std::endl;
|
||||
// ofs << " UV: (" << (float)it.uv[0] << ", " << (float)it.uv[1] << ", "
|
||||
// << (float)it.uv[2] << ", " << (float)it.uv[3] << ")" << std::endl;
|
||||
// }
|
||||
// ofs.close();
|
||||
}
|
||||
|
||||
void LI::Init() {
|
||||
vertex_buffer.resize(4 * 4096);
|
||||
idx_buffer.resize(6 * 4096);
|
||||
|
||||
li7_dvlb = DVLB_ParseFile((u32*)li7_shader, li7_shader_size);
|
||||
shaderProgramInit(&li7_prog);
|
||||
shaderProgramSetVsh(&li7_prog, &li7_dvlb->DVLE[0]);
|
||||
uLoc_proj =
|
||||
shaderInstanceGetUniformLocation(li7_prog.vertexShader, "projection");
|
||||
|
||||
AttrInfo_Init(&li7_attr);
|
||||
AttrInfo_AddLoader(&li7_attr, 0, GPU_FLOAT, 3);
|
||||
AttrInfo_AddLoader(&li7_attr, 1, GPU_FLOAT, 2);
|
||||
AttrInfo_AddLoader(&li7_attr, 2, GPU_UNSIGNED_BYTE, 4);
|
||||
|
||||
single_color = Texture::New();
|
||||
std::vector<unsigned char> pixels(16 * 16 * 4, 255);
|
||||
single_color->LoadPixels(pixels, 16, 16);
|
||||
// C3D_Tex* w = new C3D_Tex;
|
||||
// C3D_TexInit(w, 16, 16, GPU_L8);
|
||||
// C3D_TexLoadImage(w, pixels.data(), GPU_TEXFACE_2D, 0);
|
||||
// single_color->ExternalLoad(w, NVec2(16, 16), NVec4(0, 1, 1, 0));
|
||||
|
||||
font = LIFont::New();
|
||||
font->LoadSystemFont();
|
||||
}
|
||||
|
||||
void LI::Exit() {
|
||||
shaderProgramFree(&li7_prog);
|
||||
DVLB_Free(li7_dvlb);
|
||||
}
|
||||
|
||||
void LI::OnScreen(bool bottom) {
|
||||
screen_size[0] = bottom ? 320 : 400;
|
||||
screen_size[1] = 240;
|
||||
bottom_screen = bottom;
|
||||
}
|
||||
|
||||
bool LI::CompareCommands(const LI::Cmd& a, const LI::Cmd& b) {
|
||||
if (a.layer == b.layer) {
|
||||
if (a.tex == b.tex) return a.index < b.index;
|
||||
return a.tex > b.tex;
|
||||
}
|
||||
return a.layer < b.layer;
|
||||
}
|
||||
|
||||
void LI::RotateCorner(NVec2& v, float s, float c) {
|
||||
float x = v[0] * c - v[1] * s;
|
||||
float y = v[1] * c + v[0] * s;
|
||||
v = NVec2(x, y);
|
||||
}
|
||||
|
||||
void LI::MakeRect(NVec4& top, NVec4& bot, NVec2 pos, NVec2 szs, float angle) {
|
||||
NVec2 c; // Center
|
||||
NVec2 tl(-c[0], -c[1]); // Top Left Corner
|
||||
NVec2 tr(-c[0] + szs[0], -c[1]); // Top Right Corner
|
||||
NVec2 bl(-c[0], -c[1] + szs[1]); // Bottom Left Corner
|
||||
NVec2 br(-c[0] + szs[0], -c[1] + szs[1]); // Bottom Right Corner
|
||||
|
||||
// Calculate Rotation if required
|
||||
if (angle != 0.f) {
|
||||
float s = std::sin(angle);
|
||||
float c = std::cos(angle);
|
||||
RotateCorner(tl, s, c);
|
||||
RotateCorner(tr, s, c);
|
||||
RotateCorner(bl, s, c);
|
||||
RotateCorner(br, s, c);
|
||||
}
|
||||
|
||||
// Generate top and bottom positions
|
||||
top = NVec4(tl + pos + c, tr + pos + c);
|
||||
bot = NVec4(bl + pos + c, br + pos + c);
|
||||
}
|
||||
|
||||
void LI::RenderFrame(bool bottom) {
|
||||
Palladium::Ftrace::ScopedTrace st(
|
||||
"LI", "Render" + std::string(bottom ? "Bot" : "Top"));
|
||||
// Create and Setup Projection Matrix
|
||||
C3D_Mtx proj;
|
||||
Mtx_OrthoTilt(&proj, 0.f, (bottom ? 320 : 400), screen_size[1], 0.f, 1.f,
|
||||
-1.f, false);
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_proj, &proj);
|
||||
|
||||
// Disable Depth Test
|
||||
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
|
||||
|
||||
bool sfr = false;
|
||||
|
||||
// Set Tex Env to use Texture 0
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0);
|
||||
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||
|
||||
// Setup vars for performance data
|
||||
int total_vertices = 0;
|
||||
int total_indices = 0;
|
||||
num_drawcalls = 0;
|
||||
|
||||
// Get DrawCmd List and reverse it
|
||||
auto& draw_cmds = draw_lists[bottom];
|
||||
if (flags & PDLithiumFlags_LRS) {
|
||||
std::sort(draw_cmds.begin(), draw_cmds.end(), CompareCommands);
|
||||
}
|
||||
num_commands = draw_cmds.size();
|
||||
size_t index = 0;
|
||||
// Process Command List
|
||||
while (index < draw_cmds.size()) {
|
||||
// Get Active Texture and Setup Vertex List for every command with same tex
|
||||
C3D_Tex* texture = draw_cmds[index].tex->Get();
|
||||
size_t start_vtx = vertex_index;
|
||||
size_t start_idx = idx_index;
|
||||
|
||||
while (index < draw_cmds.size() && draw_cmds[index].tex->Get() == texture) {
|
||||
auto c = draw_cmds[index];
|
||||
if (c.sfr != sfr) {
|
||||
if (c.sfr == 0) {
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR,
|
||||
(GPU_TEVSRC)0);
|
||||
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||
} else if (c.sfr == 1) {
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0,
|
||||
(GPU_TEVSRC)0);
|
||||
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
|
||||
C3D_TexEnvSrc(env, C3D_Alpha, GPU_PRIMARY_COLOR, GPU_TEXTURE0,
|
||||
(GPU_TEVSRC)0);
|
||||
C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
|
||||
}
|
||||
sfr = c.sfr;
|
||||
}
|
||||
// FCS
|
||||
if (c.fcs) {
|
||||
c.top[0] = std::floor(c.top[0]);
|
||||
c.top[1] = std::floor(c.top[1]);
|
||||
c.top[2] = std::ceil(c.top[2]);
|
||||
c.top[3] = std::floor(c.top[3]);
|
||||
c.bot[0] = std::floor(c.bot[0]);
|
||||
c.bot[1] = std::ceil(c.bot[1]);
|
||||
c.bot[2] = std::ceil(c.bot[2]);
|
||||
c.bot[3] = std::ceil(c.bot[3]);
|
||||
}
|
||||
if (c.cmd_type == 1) {
|
||||
// Tiangle 1
|
||||
idx_buffer[idx_index++] = vertex_index + 0;
|
||||
idx_buffer[idx_index++] = vertex_index + 1;
|
||||
idx_buffer[idx_index++] = vertex_index + 2;
|
||||
// Tirangle 2
|
||||
idx_buffer[idx_index++] = vertex_index + 0;
|
||||
idx_buffer[idx_index++] = vertex_index + 2;
|
||||
idx_buffer[idx_index++] = vertex_index + 3;
|
||||
|
||||
// Vertices
|
||||
vertex_buffer[vertex_index++] =
|
||||
Vtx(NVec2(c.bot[2], c.bot[3]), c.uv[2], c.uv[3], c.clr);
|
||||
vertex_buffer[vertex_index++] =
|
||||
Vtx(NVec2(c.top[2], c.top[3]), c.uv[2], c.uv[1], c.clr);
|
||||
vertex_buffer[vertex_index++] =
|
||||
Vtx(NVec2(c.top[0], c.top[1]), c.uv[0], c.uv[1], c.clr);
|
||||
vertex_buffer[vertex_index++] =
|
||||
Vtx(NVec2(c.bot[0], c.bot[1]), c.uv[0], c.uv[3], c.clr);
|
||||
} else if (c.cmd_type == 2) {
|
||||
// Triangle
|
||||
idx_buffer[idx_index++] = vertex_index + 0;
|
||||
idx_buffer[idx_index++] = vertex_index + 1;
|
||||
idx_buffer[idx_index++] = vertex_index + 2;
|
||||
// Vertices
|
||||
vertex_buffer[vertex_index++] =
|
||||
Vtx(NVec2(c.bot[0], c.bot[1]), c.uv[0], c.uv[3], c.clr);
|
||||
vertex_buffer[vertex_index++] =
|
||||
Vtx(NVec2(c.top[2], c.top[3]), c.uv[2], c.uv[3], c.clr);
|
||||
vertex_buffer[vertex_index++] =
|
||||
Vtx(NVec2(c.top[0], c.top[1]), c.uv[0], c.uv[1], c.clr);
|
||||
} else if (c.cmd_type == 3) {
|
||||
for (size_t i = 1; i < (size_t)c.top[3] - 1; i++) {
|
||||
idx_buffer[idx_index++] = vertex_index;
|
||||
idx_buffer[idx_index++] = vertex_index + i + 1;
|
||||
idx_buffer[idx_index++] = vertex_index + i;
|
||||
}
|
||||
float as = 2.0f * M_PI / c.top[3];
|
||||
for (int i = 0; i < (int)c.top[3]; i++) {
|
||||
float a = i * as;
|
||||
float x = c.top[0] + c.top[2] * cos(a);
|
||||
float y = c.top[1] + c.top[2] * sin(a);
|
||||
vertex_buffer[vertex_index++] =
|
||||
Vtx(NVec2(x, y), (cos(a) + 1) / 2, (sin(a) + 1) / 2, c.clr);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
// Bind Texture
|
||||
C3D_TexBind(0, texture);
|
||||
|
||||
// Setup Buffer
|
||||
C3D_BufInfo* bufinfo = C3D_GetBufInfo();
|
||||
BufInfo_Init(bufinfo);
|
||||
BufInfo_Add(bufinfo, vertex_buffer.data(), sizeof(Vtx), 3, 0x210);
|
||||
|
||||
// Draw
|
||||
C3D_DrawElements(GPU_TRIANGLES, idx_index - start_idx, C3D_UNSIGNED_SHORT,
|
||||
idx_buffer.data() + start_idx);
|
||||
|
||||
num_drawcalls++;
|
||||
total_vertices += vertex_index - start_vtx;
|
||||
total_indices += idx_index - start_idx;
|
||||
}
|
||||
draw_cmds.clear();
|
||||
// Enable DepthTest
|
||||
C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL);
|
||||
num_vertices = total_vertices;
|
||||
num_indices = total_indices;
|
||||
active_texture = nullptr;
|
||||
}
|
||||
|
||||
void LI::Render(C3D_RenderTarget* top, C3D_RenderTarget* bot) {
|
||||
Palladium::Ftrace::ScopedTrace st("Li7", "Render");
|
||||
if (font_update) {
|
||||
text_sizes.clear();
|
||||
font_update = false;
|
||||
}
|
||||
vertex_index = 0;
|
||||
idx_index = 0;
|
||||
C3D_BindProgram(&li7_prog);
|
||||
C3D_SetAttrInfo(&li7_attr);
|
||||
C3D_FrameDrawOn(top);
|
||||
RenderFrame(false);
|
||||
int d_tmp_cmds1 = num_commands;
|
||||
int d_tmp_dcls1 = num_drawcalls;
|
||||
int d_tmp_vtxs1 = num_vertices;
|
||||
int d_tmp_idx1 = num_indices;
|
||||
C3D_FrameDrawOn(bot);
|
||||
RenderFrame(true);
|
||||
num_commands += d_tmp_cmds1;
|
||||
num_drawcalls += d_tmp_dcls1;
|
||||
num_vertices += d_tmp_vtxs1;
|
||||
num_indices += d_tmp_idx1;
|
||||
layer = 0;
|
||||
cmd_index = 0;
|
||||
if (flags & PDLithiumFlags_TMS) {
|
||||
std::vector<std::string> rem;
|
||||
for (auto& it : text_sizes) {
|
||||
if (Palladium::GetTime() - it.second.time_created > 5)
|
||||
rem.push_back(it.first);
|
||||
}
|
||||
for (auto it : rem) text_sizes.erase(it);
|
||||
} else {
|
||||
if (text_sizes.size()) text_sizes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void LI::DrawRect(NVec2 pos, NVec2 size, unsigned int clr, NVec4 uvs) {
|
||||
Cmd c;
|
||||
if (pos[0] > screen_size[0] || pos[0] + size[0] < 0 ||
|
||||
pos[1] > screen_size[1] || pos[1] + size[1] < 0)
|
||||
return;
|
||||
|
||||
MakeRect(c.top, c.bot, pos, size);
|
||||
c.fcs = flags & PDLithiumFlags_FCS;
|
||||
c.uv = uvs;
|
||||
c.clr = clr;
|
||||
c.tex = active_texture;
|
||||
c.cmd_type = 1;
|
||||
c.layer = layer;
|
||||
c.sfr = sysfont_render;
|
||||
c.index = cmd_index++;
|
||||
sysfont_render = false;
|
||||
draw_lists[bottom_screen].push_back(c);
|
||||
}
|
||||
|
||||
void LI::DrawTriangle(NVec2 a, NVec2 b, NVec2 c, unsigned int clr) {
|
||||
UseTexture();
|
||||
Cmd cmd;
|
||||
if ((a[0] > screen_size[0] && b[0] > screen_size[0] &&
|
||||
c[0] > screen_size[0]) ||
|
||||
(a[1] > screen_size[1] && b[1] > screen_size[1] &&
|
||||
c[1] > screen_size[1]) ||
|
||||
(a[0] < 0 && b[0] < 0 && c[0] < 0) || (a[1] < 0 && b[1] < 0 && c[1] < 0))
|
||||
return;
|
||||
cmd.fcs = flags & PDLithiumFlags_FCS;
|
||||
cmd.top = NVec4(a, b);
|
||||
cmd.bot = NVec4(c, NVec2());
|
||||
cmd.uv = NVec4(0, 1, 1, 0);
|
||||
cmd.layer = layer;
|
||||
cmd.clr = clr;
|
||||
cmd.tex = active_texture;
|
||||
cmd.cmd_type = 2;
|
||||
cmd.index = cmd_index++;
|
||||
draw_lists[bottom_screen].push_back(cmd);
|
||||
}
|
||||
|
||||
void LI::DrawCircle(NVec2 pos, float r, unsigned int color, int segments) {
|
||||
if (segments < 3) return;
|
||||
Cmd c;
|
||||
// Not Tested yet ...
|
||||
c.fcs = flags & PDLithiumFlags_FCS;
|
||||
c.top = NVec4(pos, NVec2(r, segments));
|
||||
c.bot = NVec4();
|
||||
c.uv = NVec4(0, 1, 1, 0);
|
||||
c.clr = color;
|
||||
c.tex = active_texture;
|
||||
c.layer = layer;
|
||||
c.cmd_type = 3;
|
||||
c.index = cmd_index++;
|
||||
draw_lists[bottom_screen].push_back(c);
|
||||
}
|
||||
|
||||
void LI::DrawLine(NVec2 a, NVec2 b, unsigned int clr, int t) {
|
||||
UseTexture();
|
||||
NVec2 direction = {b[0] - a[0], b[1] - a[1]};
|
||||
float length =
|
||||
std::sqrt(direction[0] * direction[0] + direction[1] * direction[1]);
|
||||
NVec2 unit_direction = {direction[0] / length, direction[1] / length};
|
||||
NVec2 perpendicular = {-unit_direction[1], unit_direction[0]};
|
||||
float half_t = t / 2.0f;
|
||||
NVec2 offset = {perpendicular[0] * half_t, perpendicular[1] * half_t};
|
||||
|
||||
// Calculate corner positions
|
||||
float px0 = a[0] + offset[0];
|
||||
float py0 = a[1] + offset[1];
|
||||
float px1 = b[0] + offset[0];
|
||||
float py1 = b[1] + offset[1];
|
||||
float px2 = a[0] - offset[0];
|
||||
float py2 = a[1] - offset[1];
|
||||
float px3 = b[0] - offset[0];
|
||||
float py3 = b[1] - offset[1];
|
||||
|
||||
Cmd c;
|
||||
// Schould be always true as lines otherwise could disappear for some reason
|
||||
c.fcs = flags & PDLithiumFlags_FCS;
|
||||
c.top = NVec4(px2, py2, px3, py3);
|
||||
c.bot = NVec4(px0, py0, px1, py1);
|
||||
c.uv = NVec4(0, 1, 1, 0);
|
||||
c.clr = clr;
|
||||
c.tex = active_texture;
|
||||
c.layer = layer;
|
||||
c.cmd_type = 1;
|
||||
c.index = cmd_index++;
|
||||
draw_lists[bottom_screen].push_back(c);
|
||||
}
|
||||
|
||||
std::string LI::WrapText(const std::string& in, int maxlen, NVec2& dim) {
|
||||
if (flags & PDLithiumFlags_TMS) {
|
||||
if (text_sizes.find(in) != text_sizes.end()) {
|
||||
text_sizes[in].time_created = Palladium::GetTime();
|
||||
dim = text_sizes[in].size;
|
||||
if (text_sizes[in].optinal) return text_sizes[in].text;
|
||||
}
|
||||
}
|
||||
std::string out;
|
||||
std::string line;
|
||||
int line_x = 0;
|
||||
std::istringstream istream(in);
|
||||
std::string temp;
|
||||
|
||||
while (istream >> temp) {
|
||||
NVec2 dim = GetTextDimensions(line + temp);
|
||||
if (line_x + dim[0] <= maxlen) {
|
||||
line += temp + ' ';
|
||||
line_x += dim[0];
|
||||
} else {
|
||||
out += line + '\n';
|
||||
line = temp + ' ';
|
||||
line_x = GetTextDimensions(line)[0];
|
||||
}
|
||||
}
|
||||
out += line;
|
||||
dim = GetTextDimensions(out);
|
||||
if (flags & PDLithiumFlags_TMS) {
|
||||
text_sizes[in] = TextBox{dim, Palladium::GetTime(), true, out};
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string LI::ShortText(const std::string& in, int maxlen, NVec2& dim) {
|
||||
auto textdim = GetTextDimensions(in);
|
||||
if (textdim[0] < (float)maxlen) return in;
|
||||
if (flags & PDLithiumFlags_TMS) {
|
||||
if (text_sizes.find(in) != text_sizes.end()) {
|
||||
text_sizes[in].time_created = Palladium::GetTime();
|
||||
dim = text_sizes[in].size;
|
||||
if (text_sizes[in].optinal) return text_sizes[in].text;
|
||||
}
|
||||
}
|
||||
std::string ext = "";
|
||||
std::string ph = "(...)"; // placeholder
|
||||
std::string worker = in;
|
||||
std::string out;
|
||||
size_t ext_pos = in.find_last_of('.');
|
||||
if (ext_pos != in.npos) {
|
||||
ext = in.substr(ext_pos);
|
||||
worker = in.substr(0, ext_pos);
|
||||
}
|
||||
|
||||
maxlen -= GetTextDimensions(ext)[0];
|
||||
maxlen -= GetTextDimensions(ph)[0];
|
||||
|
||||
for (auto& it : worker) {
|
||||
if (GetTextDimensions(out)[0] > (float)maxlen) {
|
||||
out += ph;
|
||||
out += ext;
|
||||
dim = GetTextDimensions(out);
|
||||
if (flags & PDLithiumFlags_TMS) {
|
||||
text_sizes[in] = TextBox{dim, Palladium::GetTime(), true, out};
|
||||
}
|
||||
return out;
|
||||
}
|
||||
out += it;
|
||||
}
|
||||
return out; // Impossible to reach
|
||||
}
|
||||
|
||||
NVec2 LI::GetTextDimensions(const std::string& text) {
|
||||
if (!font) return NVec2();
|
||||
if (flags & PDLithiumFlags_TMS) {
|
||||
if (text_sizes.find(text) != text_sizes.end()) {
|
||||
text_sizes[text].time_created = Palladium::GetTime();
|
||||
return text_sizes[text].size;
|
||||
}
|
||||
}
|
||||
// FONT
|
||||
auto txt = make_wstring(text + "\0");
|
||||
NVec2 pos(0, 0); // Temp Pos
|
||||
NVec2 offset;
|
||||
float txt_scale = text_scale;
|
||||
if (font->IsSystemFont()) txt_scale *= 0.9;
|
||||
float gapm = 1;
|
||||
float maxWidth = 0.f;
|
||||
float ntxtszs = default_font_size * txt_scale;
|
||||
float cpm = ntxtszs / font->GetPixelHeight();
|
||||
float line_height = font->GetPixelHeight() * cpm;
|
||||
|
||||
for (size_t i = 0; i < txt.length(); i++) {
|
||||
if (txt[i] == '\0') break;
|
||||
auto cp = font->GetCodepoint(txt[i]);
|
||||
if (cp.invalid && txt[i] != '\n' && txt[i] != ' ' && txt[i] != '\t')
|
||||
continue;
|
||||
bool implicitBreak = false;
|
||||
if (txt[i] == '\n' || implicitBreak) {
|
||||
offset[1] += line_height;
|
||||
maxWidth = std::max(maxWidth, offset[0]);
|
||||
offset[0] = 0;
|
||||
if (implicitBreak) continue;
|
||||
} else if (txt[i] == '\t') {
|
||||
offset[0] = ((offset[0] / ntxtszs) / 4 + 1) * 4 * ntxtszs;
|
||||
} else {
|
||||
if (txt[i] == ' ') {
|
||||
// this will make the space twice
|
||||
if (!font->IsSystemFont()) offset[0] += 4 * gapm * txt_scale;
|
||||
}
|
||||
if (i == txt.length() - 1)
|
||||
offset[0] += cp.szs[0] * cpm + txt_scale;
|
||||
else
|
||||
offset[0] += cp.szs[0] * cpm + (gapm * txt_scale);
|
||||
}
|
||||
}
|
||||
maxWidth = std::max(maxWidth, offset[0]);
|
||||
NVec2 res = NVec2(maxWidth, offset[1] + (default_font_size * txt_scale));
|
||||
if (flags & PDLithiumFlags_TMS)
|
||||
text_sizes[text] = TextBox{res, Palladium::GetTime(), false, ""};
|
||||
return res;
|
||||
}
|
||||
|
||||
void LI::DrawText(NVec2 pos, unsigned int color, const std::string& text,
|
||||
PDTextFlags flags, NVec2 ap) {
|
||||
if (!font) return;
|
||||
PDLithiumFlags tmp_flags = flags;
|
||||
// Do not use FCS in Text Rendering...
|
||||
flags &= ~PDLithiumFlags_FCS;
|
||||
std::string txt = text;
|
||||
NVec2 offset;
|
||||
float txt_scale = text_scale;
|
||||
if (font->IsSystemFont()) txt_scale *= 0.9;
|
||||
float gapm = 1;
|
||||
float ntxtszs = default_font_size * txt_scale;
|
||||
float cpm = ntxtszs / font->GetPixelHeight();
|
||||
float line_height = font->GetPixelHeight() * cpm;
|
||||
NVec2 td;
|
||||
if (flags & PDTextFlags_Wrap)
|
||||
txt = WrapText(text, ap[0] - pos[0], td);
|
||||
else if (flags & PDTextFlags_Short)
|
||||
txt = ShortText(text, ap[0] - pos[0], td);
|
||||
if (td[0] == 0 && td[1] == 0) td = GetTextDimensions(text);
|
||||
if (flags & PDTextFlags_AlignRight)
|
||||
pos[0] -= td[0];
|
||||
else if (flags & PDTextFlags_AlignMid) {
|
||||
pos[0] = (ap[0] * 0.5) - (td[0] * 0.5) + pos[0];
|
||||
}
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream iss(txt);
|
||||
std::string temp;
|
||||
while (std::getline(iss, temp)) {
|
||||
lines.push_back(temp);
|
||||
}
|
||||
|
||||
for (auto& it : lines) {
|
||||
if (pos[1] + offset[1] + line_height < 0) {
|
||||
offset[1] += line_height;
|
||||
continue;
|
||||
} else if (pos[1] + offset[1] > screen_size[1]) {
|
||||
// Break func as we dont want loop over lines that get skipped too
|
||||
break;
|
||||
}
|
||||
auto wstr = make_wstring(it);
|
||||
// Loop over line
|
||||
for (auto& jt : wstr) {
|
||||
auto cp = font->GetCodepoint(jt);
|
||||
if (cp.invalid && jt != '\n' && jt != ' ' && jt != '\t') continue;
|
||||
active_texture = cp.tex;
|
||||
if (jt == '\t') {
|
||||
offset[0] = ((offset[0] / ntxtszs) / 4 + 1) * 4 * ntxtszs;
|
||||
} else {
|
||||
if (jt != ' ') {
|
||||
int lr = layer;
|
||||
if (flags & PDTextFlags_Shaddow) {
|
||||
sysfont_render = true;
|
||||
DrawRect(
|
||||
pos + NVec2(offset[0] + 1, (offset[1] + (cp.off * cpm)) + 1),
|
||||
NVec2(cp.szs[0] * cpm, cp.szs[1] * cpm),
|
||||
Palladium::Color::RGBA(color).is_light() ? 0xff111111
|
||||
: 0xffeeeeee,
|
||||
cp.uv);
|
||||
layer++;
|
||||
}
|
||||
sysfont_render = true;
|
||||
DrawRect(pos + offset + NVec2(0, (cp.off * cpm)),
|
||||
NVec2(cp.szs[0] * cpm, cp.szs[1] * cpm), color, cp.uv);
|
||||
layer = lr;
|
||||
|
||||
} else {
|
||||
// this will make the space twice
|
||||
if (!font->IsSystemFont()) offset[0] += 4 * gapm * txt_scale;
|
||||
}
|
||||
offset[0] += cp.szs[0] * cpm + (gapm * txt_scale);
|
||||
}
|
||||
}
|
||||
offset[1] += line_height;
|
||||
offset[0] = 0;
|
||||
}
|
||||
flags = tmp_flags;
|
||||
}
|
||||
} // namespace Palladium
|
@ -1,94 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <pd/Lithium.hpp>
|
||||
#include <pd/Message.hpp>
|
||||
#include <pd/base/Color.hpp>
|
||||
#include <pd/palladium.hpp>
|
||||
#include <vector>
|
||||
|
||||
extern bool pdi_debugging;
|
||||
|
||||
static std::vector<std::shared_ptr<Palladium::Message>> msg_lst;
|
||||
static int fade_outs = 200; // Start of fadeout
|
||||
static int idles = 60; // start of Idle
|
||||
static int anim_len = 300; // Full Length of Animation
|
||||
static NVec2 msg_box = NVec2(170, 50); // Message Box Size
|
||||
|
||||
NVec2 MakePos(float anim_time, int entry) {
|
||||
float fol = anim_len - fade_outs;
|
||||
if (anim_time > fade_outs)
|
||||
return NVec2(
|
||||
5, static_cast<int>(240 - ((entry + 1) * 55) - 5 +
|
||||
(float)((anim_time - fade_outs) / fol) * -20));
|
||||
if (anim_time > idles) return NVec2(5, 240 - ((entry + 1) * 55) - 5);
|
||||
return NVec2(
|
||||
static_cast<int>(-150 + ((float)(anim_time / (float)idles) * 155)),
|
||||
240 - ((entry + 1) * 55) - 5);
|
||||
}
|
||||
|
||||
namespace Palladium {
|
||||
float GetDeltaTime(); // Extern from Palladium.cpp
|
||||
|
||||
void ProcessMessages() {
|
||||
float tmp_txt = LI::GetTextScale();
|
||||
LI::DefaultTextScale();
|
||||
// Draw in ovl mode
|
||||
LI::OnScreen(false);
|
||||
LI::NewLayer();
|
||||
float fol = anim_len - fade_outs;
|
||||
std::reverse(msg_lst.begin(), msg_lst.end());
|
||||
for (size_t i = 0; i < msg_lst.size(); i++) {
|
||||
NVec2 pos = MakePos(msg_lst[i]->animtime, i);
|
||||
if ((pos.y() + 150) < 0) {
|
||||
// Dont Render Out of Screen
|
||||
// And as thay aren't relevant anymore
|
||||
// Thay get deleted!
|
||||
msg_lst.erase(msg_lst.begin() + i);
|
||||
} else {
|
||||
int new_alpha = 200;
|
||||
if (msg_lst[i]->animtime > fade_outs) {
|
||||
new_alpha = 200 - (float(msg_lst[i]->animtime - fade_outs) / fol) * 200;
|
||||
}
|
||||
// Wtf is this function lol
|
||||
auto bgc = Palladium::Color::RGBA(PDColor_MessageBackground)
|
||||
.changeA(new_alpha)
|
||||
.toRGBA();
|
||||
auto tc =
|
||||
Palladium::Color::RGBA(PDColor_Text2).changeA(new_alpha).toRGBA();
|
||||
LI::DrawRect(pos, msg_box, bgc);
|
||||
LI::NewLayer();
|
||||
LI::DrawText(pos + NVec2(5, 1), tc, msg_lst[i]->title);
|
||||
LI::DrawText(pos + NVec2(5, 17), tc, msg_lst[i]->message);
|
||||
if (pdi_debugging)
|
||||
LI::DrawText(pos + NVec2(msg_box.x() + 5, 1), tc,
|
||||
std::to_string((int)msg_lst[i]->animtime));
|
||||
// fix for Startup lol
|
||||
// Todo: Only do this on AppStart
|
||||
if (msg_lst[i]->animtime == 0) {
|
||||
msg_lst[i]->animtime += 1;
|
||||
} else {
|
||||
msg_lst[i]->animtime += Palladium::GetDeltaTime() * 0.1f;
|
||||
}
|
||||
if (msg_lst[i]->animtime > anim_len) {
|
||||
msg_lst.erase(msg_lst.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ReReverse ?? lol
|
||||
// Cause otherwise the Toasts will swap
|
||||
std::reverse(msg_lst.begin(), msg_lst.end());
|
||||
LI::SetTextScale(tmp_txt);
|
||||
}
|
||||
|
||||
void PushMessage(const Message &msg) {
|
||||
msg_lst.push_back(std::make_shared<Palladium::Message>(msg));
|
||||
}
|
||||
|
||||
void SetMessageIdleStartFrame(int frame) { idles = frame; }
|
||||
|
||||
void SetMessageTotalAnimationFrames(int total_frames) {
|
||||
anim_len = total_frames;
|
||||
}
|
||||
|
||||
void SetMessageFadeOutStartFrame(int frame) { fade_outs = frame; }
|
||||
} // namespace Palladium
|
243
source/Net.cpp
243
source/Net.cpp
@ -1,243 +0,0 @@
|
||||
// TODO: Make Download2File faster on large files
|
||||
|
||||
#include <3ds.h>
|
||||
#include <curl/curl.h>
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <pd/Net.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
#include <regex>
|
||||
|
||||
static Palladium::Net::Error pdi_check_wifi() {
|
||||
// if (pdi_is_citra) return 0;
|
||||
int s = osGetWifiStrength();
|
||||
return (s == 0 ? Palladium::Net::Error_NoWifi : 0);
|
||||
}
|
||||
|
||||
static size_t pdi_handle_data(char* ptr, size_t size, size_t nmemb,
|
||||
void* userdata) {
|
||||
size_t ms = size * nmemb;
|
||||
((std::string*)userdata)->append(ptr, ms);
|
||||
return ms;
|
||||
}
|
||||
|
||||
static size_t pdi_handle_file(char* ptr, size_t size, size_t nmemb, void* out) {
|
||||
size_t ms = size * nmemb;
|
||||
((std::ofstream*)out)->write(reinterpret_cast<const char*>(ptr), ms);
|
||||
return ms;
|
||||
}
|
||||
|
||||
struct pdi_net_dl {
|
||||
unsigned long long current = 0;
|
||||
unsigned long long total = 1;
|
||||
void Reset() {
|
||||
current = 0;
|
||||
total = 1;
|
||||
}
|
||||
};
|
||||
|
||||
static pdi_net_dl pdi_net_dl_spec;
|
||||
|
||||
static int pdi_handle_curl_progress(CURL* hnd, curl_off_t dltotal,
|
||||
curl_off_t dlnow, curl_off_t ultotal,
|
||||
curl_off_t ulnow) {
|
||||
pdi_net_dl_spec.total = dltotal;
|
||||
pdi_net_dl_spec.current = dlnow;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pdi_setup_curl_context(CURL* hnd, const std::string& url,
|
||||
void* userptr, bool mem) {
|
||||
std::string user_agent =
|
||||
pdi_app_name + "/Palladium (Version: " + std::string(PDVSTRING) + ")";
|
||||
|
||||
if (!mem) {
|
||||
curl_easy_setopt(hnd, CURLOPT_FAILONERROR, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_ACCEPT_ENCODING, "gzip");
|
||||
curl_easy_setopt(hnd, CURLOPT_XFERINFOFUNCTION, pdi_handle_curl_progress);
|
||||
}
|
||||
|
||||
curl_easy_setopt(hnd, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 0L);
|
||||
curl_easy_setopt(hnd, CURLOPT_USERAGENT, user_agent.c_str());
|
||||
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, userptr);
|
||||
curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
|
||||
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
|
||||
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION,
|
||||
mem ? pdi_handle_data : pdi_handle_file);
|
||||
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_STDERR, stdout);
|
||||
}
|
||||
|
||||
static bool pdi_curl_is_busy = false;
|
||||
static bool pdi_apir_is_busy = false;
|
||||
|
||||
namespace Palladium {
|
||||
namespace Net {
|
||||
Error Download(const std::string& url, std::string& data) {
|
||||
if (pdi_curl_is_busy) return Error_Busy;
|
||||
Error ret = pdi_check_wifi();
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
pdi_curl_is_busy = true;
|
||||
pdi_net_dl_spec.Reset();
|
||||
|
||||
auto hnd = curl_easy_init();
|
||||
pdi_setup_curl_context(hnd, url, &data, true);
|
||||
|
||||
CURLcode curl_res = curl_easy_perform(hnd);
|
||||
curl_easy_cleanup(hnd);
|
||||
|
||||
if (curl_res != CURLE_OK) {
|
||||
data.clear();
|
||||
pdi_curl_is_busy = false;
|
||||
return ((static_cast<Error>(curl_res) << 32) |
|
||||
static_cast<Error>(Error_Curl));
|
||||
}
|
||||
|
||||
pdi_curl_is_busy = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Error Download2File(const std::string& url, const std::string& path) {
|
||||
if (pdi_curl_is_busy) return Error_Busy;
|
||||
Error ret = pdi_check_wifi();
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
pdi_curl_is_busy = true;
|
||||
pdi_net_dl_spec.Reset();
|
||||
// std::filesystem::create_directories(
|
||||
// std::filesystem::path(path).remove_filename());
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
|
||||
if (!file.is_open()) {
|
||||
pdi_curl_is_busy = false;
|
||||
return Error_Write;
|
||||
}
|
||||
|
||||
auto hnd = curl_easy_init();
|
||||
pdi_setup_curl_context(hnd, url, &file, false);
|
||||
|
||||
CURLcode curl_res = curl_easy_perform(hnd);
|
||||
curl_easy_cleanup(hnd);
|
||||
|
||||
file.close();
|
||||
if (curl_res != CURLE_OK) {
|
||||
if (Palladium::FS::FileExist(path)) {
|
||||
std::filesystem::remove(path);
|
||||
}
|
||||
pdi_curl_is_busy = false;
|
||||
return ((static_cast<Error>(curl_res) << 32) |
|
||||
static_cast<Error>(Error_Curl));
|
||||
}
|
||||
|
||||
pdi_curl_is_busy = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Error GitDownloadRelease(const std::string& url, const std::string& asset_name,
|
||||
const std::string& path, bool prerelease) {
|
||||
if (pdi_apir_is_busy) return Error_Busy;
|
||||
Error ret = pdi_check_wifi();
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
pdi_apir_is_busy = true;
|
||||
std::regex parse("github\\.com\\/(.+)\\/(.+)");
|
||||
std::smatch res;
|
||||
std::regex_search(url, res, parse);
|
||||
|
||||
std::string user = res[1].str();
|
||||
std::string repo = res[2].str();
|
||||
|
||||
std::stringstream req;
|
||||
req << "https://api.github.com/repos/" << user << "/" << repo
|
||||
<< (prerelease ? "/releases" : "/releases/latest");
|
||||
|
||||
std::string buf;
|
||||
ret = Download(req.str(), buf);
|
||||
if (ret) {
|
||||
pdi_apir_is_busy = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pret = 0;
|
||||
std::string freq;
|
||||
if (nlohmann::json::accept(buf)) {
|
||||
nlohmann::json api = nlohmann::json::parse(buf);
|
||||
if (!api.size()) pret = -1;
|
||||
if (pret != -1) {
|
||||
if (prerelease) api = api[0];
|
||||
if (api["assets"].is_array()) {
|
||||
for (const auto& asset : api["assets"]) {
|
||||
if (asset.is_object() && asset["name"].is_string() &&
|
||||
asset["browser_download_url"].is_string()) {
|
||||
if (std::regex_match(std::string(asset["name"]),
|
||||
std::regex(asset_name))) {
|
||||
freq = asset["browser_download_url"];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pret = -1;
|
||||
}
|
||||
|
||||
if (pret != 0 || freq.empty()) {
|
||||
pdi_apir_is_busy = false;
|
||||
return Error_Git;
|
||||
}
|
||||
|
||||
ret = Download2File(freq, path);
|
||||
pdi_apir_is_busy = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Error JsonApiRequest(const std::string& api_url, nlohmann::json& res) {
|
||||
if (pdi_apir_is_busy) return Error_Busy;
|
||||
Error ret = pdi_check_wifi();
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
pdi_apir_is_busy = true;
|
||||
|
||||
std::string buf;
|
||||
ret = Download(api_url, buf);
|
||||
if (ret) {
|
||||
pdi_apir_is_busy = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (nlohmann::json::accept(buf)) {
|
||||
res = nlohmann::json::parse(buf);
|
||||
if (!res.size()) {
|
||||
pdi_apir_is_busy = false;
|
||||
return Error_Invalid;
|
||||
}
|
||||
} else {
|
||||
pdi_apir_is_busy = false;
|
||||
return Error_Invalid;
|
||||
}
|
||||
|
||||
pdi_apir_is_busy = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long long GetProgressCurrent() { return pdi_net_dl_spec.current; }
|
||||
unsigned long long GetProgressTotal() {
|
||||
// As curl sets total to 0 we need
|
||||
// to return a 1 as devide by zeroi will crash
|
||||
if (pdi_net_dl_spec.total <= 0) return 1;
|
||||
return pdi_net_dl_spec.total;
|
||||
}
|
||||
} // namespace Net
|
||||
} // namespace Palladium
|
@ -1,616 +0,0 @@
|
||||
#include <format>
|
||||
#include <pd/Hid.hpp>
|
||||
#include <pd/Lithium.hpp>
|
||||
#include <pd/Overlays.hpp>
|
||||
#include <pd/base/FunctionTrace.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
#include <pd/palladium.hpp>
|
||||
|
||||
///////////////////////////////
|
||||
struct Key {
|
||||
std::string disp;
|
||||
NVec2 pos;
|
||||
NVec2 size;
|
||||
// 0 = default key
|
||||
// 1 = Shift
|
||||
// 2 = Backsp
|
||||
// 3 = Enter
|
||||
// 4 = Cancel
|
||||
// 5 = Confirm
|
||||
// 6 = Tab
|
||||
// 7 = Caps
|
||||
// 8 = Space
|
||||
int action = 0;
|
||||
};
|
||||
|
||||
std::vector<Key> keyboard_layout_num{
|
||||
// 1st row
|
||||
{"7", NVec2(5, 135), NVec2(36, 24), 0},
|
||||
{"8", NVec2(43, 135), NVec2(36, 24), 0},
|
||||
{"9", NVec2(81, 135), NVec2(36, 24), 0},
|
||||
// 2nd row
|
||||
{"4", NVec2(5, 161), NVec2(36, 24), 0},
|
||||
{"5", NVec2(43, 161), NVec2(36, 24), 0},
|
||||
{"6", NVec2(81, 161), NVec2(36, 24), 0},
|
||||
// 3rd row
|
||||
{"1", NVec2(5, 187), NVec2(36, 24), 0},
|
||||
{"2", NVec2(43, 187), NVec2(36, 24), 0},
|
||||
{"3", NVec2(81, 187), NVec2(36, 24), 0},
|
||||
|
||||
// 4th row
|
||||
{"0", NVec2(5, 213), NVec2(74, 24), 0},
|
||||
{".", NVec2(81, 213), NVec2(36, 24), 0},
|
||||
// additional actions
|
||||
{"<---", NVec2(119, 135), NVec2(74, 24), 2},
|
||||
//{"", NVec2(119, 161), NVec2(74, 24), 0},
|
||||
{"Confirm", NVec2(119, 187), NVec2(74, 24), 5},
|
||||
{"Cancel", NVec2(119, 213), NVec2(74, 24), 4},
|
||||
};
|
||||
|
||||
std::vector<Key> keyboard_layout = {
|
||||
// 1st row
|
||||
{"`", NVec2(5, 137), NVec2(18, 18), 0},
|
||||
{"1", NVec2(25, 137), NVec2(18, 18), 0},
|
||||
{"2", NVec2(45, 137), NVec2(18, 18), 0},
|
||||
{"3", NVec2(65, 137), NVec2(18, 18), 0},
|
||||
{"4", NVec2(85, 137), NVec2(18, 18), 0},
|
||||
{"5", NVec2(105, 137), NVec2(18, 18), 0},
|
||||
{"6", NVec2(125, 137), NVec2(18, 18), 0},
|
||||
{"7", NVec2(145, 137), NVec2(18, 18), 0},
|
||||
{"8", NVec2(165, 137), NVec2(18, 18), 0},
|
||||
{"9", NVec2(185, 137), NVec2(18, 18), 0},
|
||||
{"0", NVec2(205, 137), NVec2(18, 18), 0},
|
||||
{"-", NVec2(225, 137), NVec2(18, 18), 0},
|
||||
{"=", NVec2(245, 137), NVec2(18, 18), 0},
|
||||
{"<---", NVec2(265, 137), NVec2(50, 18), 2},
|
||||
// 2nd row
|
||||
{"Tab", NVec2(5, 157), NVec2(40, 18), 6},
|
||||
{"q", NVec2(47, 157), NVec2(18, 18), 0},
|
||||
{"w", NVec2(67, 157), NVec2(18, 18), 0},
|
||||
{"e", NVec2(87, 157), NVec2(18, 18), 0},
|
||||
{"r", NVec2(107, 157), NVec2(18, 18), 0},
|
||||
{"t", NVec2(127, 157), NVec2(18, 18), 0},
|
||||
{"y", NVec2(147, 157), NVec2(18, 18), 0},
|
||||
{"u", NVec2(167, 157), NVec2(18, 18), 0},
|
||||
{"i", NVec2(187, 157), NVec2(18, 18), 0},
|
||||
{"o", NVec2(207, 157), NVec2(18, 18), 0},
|
||||
{"p", NVec2(227, 157), NVec2(18, 18), 0},
|
||||
{"[", NVec2(247, 157), NVec2(18, 18), 0},
|
||||
{"]", NVec2(267, 157), NVec2(18, 18), 0},
|
||||
{"\\", NVec2(287, 157), NVec2(28, 18), 0},
|
||||
// 3rd row
|
||||
{"Caps", NVec2(5, 177), NVec2(50, 18), 7},
|
||||
{"a", NVec2(57, 177), NVec2(18, 18), 0},
|
||||
{"s", NVec2(77, 177), NVec2(18, 18), 0},
|
||||
{"d", NVec2(97, 177), NVec2(18, 18), 0},
|
||||
{"f", NVec2(117, 177), NVec2(18, 18), 0},
|
||||
{"g", NVec2(137, 177), NVec2(18, 18), 0},
|
||||
{"h", NVec2(157, 177), NVec2(18, 18), 0},
|
||||
{"j", NVec2(177, 177), NVec2(18, 18), 0},
|
||||
{"k", NVec2(197, 177), NVec2(18, 18), 0},
|
||||
{"l", NVec2(217, 177), NVec2(18, 18), 0},
|
||||
{";", NVec2(237, 177), NVec2(18, 18), 0},
|
||||
{"'", NVec2(257, 177), NVec2(18, 18), 0},
|
||||
{"Enter", NVec2(277, 177), NVec2(38, 18), 3},
|
||||
// 4th row
|
||||
{"Shift", NVec2(5, 197), NVec2(60, 18), 1},
|
||||
{"z", NVec2(67, 197), NVec2(18, 18), 0},
|
||||
{"x", NVec2(87, 197), NVec2(18, 18), 0},
|
||||
{"c", NVec2(107, 197), NVec2(18, 18), 0},
|
||||
{"v", NVec2(127, 197), NVec2(18, 18), 0},
|
||||
{"b", NVec2(147, 197), NVec2(18, 18), 0},
|
||||
{"n", NVec2(167, 197), NVec2(18, 18), 0},
|
||||
{"m", NVec2(187, 197), NVec2(18, 18), 0},
|
||||
{",", NVec2(207, 197), NVec2(18, 18), 0},
|
||||
{".", NVec2(227, 197), NVec2(18, 18), 0},
|
||||
{"/", NVec2(247, 197), NVec2(18, 18), 0},
|
||||
{"Shift", NVec2(267, 197), NVec2(48, 18), 1},
|
||||
// 5th row
|
||||
{"Cancel", NVec2(5, 217), NVec2(70, 18), 4},
|
||||
{"(X)", NVec2(77, 217), NVec2(23, 18), 10},
|
||||
{"Space", NVec2(102, 217), NVec2(108, 18), 8},
|
||||
{"(!)", NVec2(212, 217), NVec2(23, 18), 10},
|
||||
{"Confirm", NVec2(237, 217), NVec2(78, 18), 5},
|
||||
/*{"←", NVec2(237, 217), NVec2(18, 18)},
|
||||
{"→", NVec2(257, 217), NVec2(18, 18)},
|
||||
{"↓", NVec2(277, 217), NVec2(18, 18)},
|
||||
{"↑", NVec2(297, 217), NVec2(18, 18)},*/
|
||||
};
|
||||
|
||||
std::vector<Key> keyboard_layout_caps = {
|
||||
// 1st row
|
||||
{"`", NVec2(5, 137), NVec2(18, 18), 0},
|
||||
{"1", NVec2(25, 137), NVec2(18, 18), 0},
|
||||
{"2", NVec2(45, 137), NVec2(18, 18), 0},
|
||||
{"3", NVec2(65, 137), NVec2(18, 18), 0},
|
||||
{"4", NVec2(85, 137), NVec2(18, 18), 0},
|
||||
{"5", NVec2(105, 137), NVec2(18, 18), 0},
|
||||
{"6", NVec2(125, 137), NVec2(18, 18), 0},
|
||||
{"7", NVec2(145, 137), NVec2(18, 18), 0},
|
||||
{"8", NVec2(165, 137), NVec2(18, 18), 0},
|
||||
{"9", NVec2(185, 137), NVec2(18, 18), 0},
|
||||
{"0", NVec2(205, 137), NVec2(18, 18), 0},
|
||||
{"-", NVec2(225, 137), NVec2(18, 18), 0},
|
||||
{"=", NVec2(245, 137), NVec2(18, 18), 0},
|
||||
{"<---", NVec2(265, 137), NVec2(50, 18), 2},
|
||||
// 2nd row
|
||||
{"Tab", NVec2(5, 157), NVec2(40, 18), 6},
|
||||
{"Q", NVec2(47, 157), NVec2(18, 18), 0},
|
||||
{"W", NVec2(67, 157), NVec2(18, 18), 0},
|
||||
{"E", NVec2(87, 157), NVec2(18, 18), 0},
|
||||
{"R", NVec2(107, 157), NVec2(18, 18), 0},
|
||||
{"T", NVec2(127, 157), NVec2(18, 18), 0},
|
||||
{"Y", NVec2(147, 157), NVec2(18, 18), 0},
|
||||
{"U", NVec2(167, 157), NVec2(18, 18), 0},
|
||||
{"I", NVec2(187, 157), NVec2(18, 18), 0},
|
||||
{"O", NVec2(207, 157), NVec2(18, 18), 0},
|
||||
{"P", NVec2(227, 157), NVec2(18, 18), 0},
|
||||
{"[", NVec2(247, 157), NVec2(18, 18), 0},
|
||||
{"]", NVec2(267, 157), NVec2(18, 18), 0},
|
||||
{"\\", NVec2(287, 157), NVec2(28, 18), 0},
|
||||
// 3rd row
|
||||
{"Caps", NVec2(5, 177), NVec2(50, 18), 7},
|
||||
{"A", NVec2(57, 177), NVec2(18, 18), 0},
|
||||
{"S", NVec2(77, 177), NVec2(18, 18), 0},
|
||||
{"D", NVec2(97, 177), NVec2(18, 18), 0},
|
||||
{"F", NVec2(117, 177), NVec2(18, 18), 0},
|
||||
{"G", NVec2(137, 177), NVec2(18, 18), 0},
|
||||
{"H", NVec2(157, 177), NVec2(18, 18), 0},
|
||||
{"J", NVec2(177, 177), NVec2(18, 18), 0},
|
||||
{"K", NVec2(197, 177), NVec2(18, 18), 0},
|
||||
{"L", NVec2(217, 177), NVec2(18, 18), 0},
|
||||
{";", NVec2(237, 177), NVec2(18, 18), 0},
|
||||
{"'", NVec2(257, 177), NVec2(18, 18), 0},
|
||||
{"Enter", NVec2(277, 177), NVec2(38, 18), 3},
|
||||
// 4th row
|
||||
{"Shift", NVec2(5, 197), NVec2(60, 18), 1},
|
||||
{"Z", NVec2(67, 197), NVec2(18, 18), 0},
|
||||
{"X", NVec2(87, 197), NVec2(18, 18), 0},
|
||||
{"C", NVec2(107, 197), NVec2(18, 18), 0},
|
||||
{"V", NVec2(127, 197), NVec2(18, 18), 0},
|
||||
{"B", NVec2(147, 197), NVec2(18, 18), 0},
|
||||
{"N", NVec2(167, 197), NVec2(18, 18), 0},
|
||||
{"M", NVec2(187, 197), NVec2(18, 18), 0},
|
||||
{",", NVec2(207, 197), NVec2(18, 18), 0},
|
||||
{".", NVec2(227, 197), NVec2(18, 18), 0},
|
||||
{"/", NVec2(247, 197), NVec2(18, 18), 0},
|
||||
{"Shift", NVec2(267, 197), NVec2(48, 18), 1},
|
||||
// 5th row
|
||||
{"Cancel", NVec2(5, 217), NVec2(70, 18), 4},
|
||||
{"(X)", NVec2(77, 217), NVec2(23, 18), 10},
|
||||
{"Space", NVec2(102, 217), NVec2(108, 18), 8},
|
||||
{"(!)", NVec2(212, 217), NVec2(23, 18), 10},
|
||||
{"Confirm", NVec2(237, 217), NVec2(78, 18), 5},
|
||||
/*{"←", NVec2(237, 217), NVec2(18, 18)},
|
||||
{"→", NVec2(257, 217), NVec2(18, 18)},
|
||||
{"↑", NVec2(277, 217), NVec2(18, 18)},
|
||||
{"↓", NVec2(297, 217), NVec2(18, 18)},*/
|
||||
};
|
||||
|
||||
std::vector<Key> keyboard_layout_shift = {
|
||||
// 1st row
|
||||
{"~", NVec2(5, 137), NVec2(18, 18), 0},
|
||||
{"!", NVec2(25, 137), NVec2(18, 18), 0},
|
||||
{"@", NVec2(45, 137), NVec2(18, 18), 0},
|
||||
{"#", NVec2(65, 137), NVec2(18, 18), 0},
|
||||
{"$", NVec2(85, 137), NVec2(18, 18), 0},
|
||||
{"%", NVec2(105, 137), NVec2(18, 18), 0},
|
||||
{"^", NVec2(125, 137), NVec2(18, 18), 0},
|
||||
{"&", NVec2(145, 137), NVec2(18, 18), 0},
|
||||
{"*", NVec2(165, 137), NVec2(18, 18), 0},
|
||||
{"(", NVec2(185, 137), NVec2(18, 18), 0},
|
||||
{")", NVec2(205, 137), NVec2(18, 18), 0},
|
||||
{"_", NVec2(225, 137), NVec2(18, 18), 0},
|
||||
{"+", NVec2(245, 137), NVec2(18, 18), 0},
|
||||
{"<---", NVec2(265, 137), NVec2(50, 18), 2},
|
||||
// 2nd row
|
||||
{"Tab", NVec2(5, 157), NVec2(40, 18), 6},
|
||||
{"Q", NVec2(47, 157), NVec2(18, 18), 0},
|
||||
{"W", NVec2(67, 157), NVec2(18, 18), 0},
|
||||
{"E", NVec2(87, 157), NVec2(18, 18), 0},
|
||||
{"R", NVec2(107, 157), NVec2(18, 18), 0},
|
||||
{"T", NVec2(127, 157), NVec2(18, 18), 0},
|
||||
{"Y", NVec2(147, 157), NVec2(18, 18), 0},
|
||||
{"U", NVec2(167, 157), NVec2(18, 18), 0},
|
||||
{"I", NVec2(187, 157), NVec2(18, 18), 0},
|
||||
{"O", NVec2(207, 157), NVec2(18, 18), 0},
|
||||
{"P", NVec2(227, 157), NVec2(18, 18), 0},
|
||||
{"{", NVec2(247, 157), NVec2(18, 18), 0},
|
||||
{"}", NVec2(267, 157), NVec2(18, 18), 0},
|
||||
{"|", NVec2(287, 157), NVec2(28, 18), 0},
|
||||
// 3rd row
|
||||
{"Caps", NVec2(5, 177), NVec2(50, 18), 7},
|
||||
{"A", NVec2(57, 177), NVec2(18, 18), 0},
|
||||
{"S", NVec2(77, 177), NVec2(18, 18), 0},
|
||||
{"D", NVec2(97, 177), NVec2(18, 18), 0},
|
||||
{"F", NVec2(117, 177), NVec2(18, 18), 0},
|
||||
{"G", NVec2(137, 177), NVec2(18, 18), 0},
|
||||
{"H", NVec2(157, 177), NVec2(18, 18), 0},
|
||||
{"J", NVec2(177, 177), NVec2(18, 18), 0},
|
||||
{"K", NVec2(197, 177), NVec2(18, 18), 0},
|
||||
{"L", NVec2(217, 177), NVec2(18, 18), 0},
|
||||
{":", NVec2(237, 177), NVec2(18, 18), 0},
|
||||
{"\"", NVec2(257, 177), NVec2(18, 18), 0},
|
||||
{"Enter", NVec2(277, 177), NVec2(38, 18), 3},
|
||||
// 4th row
|
||||
{"Shift", NVec2(5, 197), NVec2(60, 18), 1},
|
||||
{"Z", NVec2(67, 197), NVec2(18, 18), 0},
|
||||
{"X", NVec2(87, 197), NVec2(18, 18), 0},
|
||||
{"C", NVec2(107, 197), NVec2(18, 18), 0},
|
||||
{"V", NVec2(127, 197), NVec2(18, 18), 0},
|
||||
{"B", NVec2(147, 197), NVec2(18, 18), 0},
|
||||
{"N", NVec2(167, 197), NVec2(18, 18), 0},
|
||||
{"M", NVec2(187, 197), NVec2(18, 18), 0},
|
||||
{"<", NVec2(207, 197), NVec2(18, 18), 0},
|
||||
{">", NVec2(227, 197), NVec2(18, 18), 0},
|
||||
{"?", NVec2(247, 197), NVec2(18, 18), 0},
|
||||
{"Shift", NVec2(267, 197), NVec2(48, 18), 1},
|
||||
// 5th row
|
||||
{"Cancel", NVec2(5, 217), NVec2(70, 18), 4},
|
||||
{"(X)", NVec2(77, 217), NVec2(23, 18), 10},
|
||||
{"Space", NVec2(102, 217), NVec2(108, 18), 8},
|
||||
{"(!)", NVec2(212, 217), NVec2(23, 18), 10},
|
||||
{"Confirm", NVec2(237, 217), NVec2(78, 18), 5},
|
||||
/*{"←", NVec2(237, 217), NVec2(18, 18)},
|
||||
{"→", NVec2(257, 217), NVec2(18, 18)},
|
||||
{"↑", NVec2(277, 217), NVec2(18, 18)},
|
||||
{"↓", NVec2(297, 217), NVec2(18, 18)},*/
|
||||
};
|
||||
|
||||
// From UI7
|
||||
bool UI7_InBox(NVec2 inpos, NVec2 boxpos, NVec2 boxsize) {
|
||||
if ((inpos.x() > boxpos.x()) && (inpos.y() > boxpos.y()) &&
|
||||
(inpos.x() < boxpos.x() + boxsize.x()) &&
|
||||
(inpos.y() < boxpos.y() + boxsize.y()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace Palladium {
|
||||
Ovl_Ftrace::Ovl_Ftrace(bool* is_enabled) { i_is_enabled = is_enabled; }
|
||||
|
||||
void Ovl_Ftrace::Draw(void) const {
|
||||
float tmp_txt = LI::GetTextScale();
|
||||
LI::DefaultTextScale();
|
||||
LI::OnScreen(false);
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_FillBg) {
|
||||
LI::NewLayer();
|
||||
Palladium::Color::RGBA bg(PDColor_Background);
|
||||
bg.changeA(150);
|
||||
LI::DrawRect(NVec2(0, 0), NVec2(400, 20), bg.toRGBA());
|
||||
}
|
||||
LI::NewLayer();
|
||||
int lrb = LI::Layer();
|
||||
std::string label = "FTrace Overlay";
|
||||
auto lbdim = LI::GetTextDimensions(label);
|
||||
LI::DrawRect(NVec2(), lbdim,
|
||||
Palladium::ThemeActive()->Get(PDColor_TextDisabled));
|
||||
LI::Layer(lrb + 1);
|
||||
LI::DrawText(NVec2(0, 0), Palladium::ThemeActive()->Get(PDColor_Text2),
|
||||
label);
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayHelp) {
|
||||
std::string hlp =
|
||||
(pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayName ? "Name" : "#");
|
||||
hlp += ": Current";
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayAverage ||
|
||||
pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMin ||
|
||||
pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMax) {
|
||||
hlp += " |";
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayAverage)
|
||||
hlp += " Avg";
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMin) hlp += " Min";
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMax) hlp += " Max";
|
||||
}
|
||||
auto hlpdim = LI::GetTextDimensions(hlp);
|
||||
LI::Layer(lrb);
|
||||
LI::DrawRect(NVec2(0, 20), hlpdim,
|
||||
Palladium::ThemeActive()->Get(PDColor_TextDisabled));
|
||||
LI::Layer(lrb + 1);
|
||||
LI::DrawText(NVec2(0, 20), Palladium::ThemeActive()->Get(PDColor_Text2),
|
||||
hlp);
|
||||
}
|
||||
|
||||
std::vector<Palladium::Ftrace::FTRes> dt;
|
||||
for (auto const& it : Palladium::Ftrace::pd_traces)
|
||||
if (it.second.is_ovl && dt.size() < 10) dt.push_back(it.second);
|
||||
for (size_t i = 0; i < (dt.size() < 10 ? dt.size() : 10); i++) {
|
||||
std::string slot = (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayName
|
||||
? dt[i].func_name
|
||||
: std::to_string(i));
|
||||
slot += ": " + MsTimeFmt(dt[i].time_of);
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayAverage ||
|
||||
pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMin ||
|
||||
pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMax) {
|
||||
slot += " |";
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayAverage)
|
||||
slot += " " + MsTimeFmt(dt[i].ts.GetAverage());
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMin)
|
||||
slot += " " + MsTimeFmt(dt[i].ts.GetMin());
|
||||
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMax)
|
||||
slot += " " + MsTimeFmt(dt[i].ts.GetMax());
|
||||
}
|
||||
auto dim = LI::GetTextDimensions(slot);
|
||||
LI::Layer(lrb);
|
||||
LI::DrawRect(NVec2(0, 37 + i * dim.y()), dim,
|
||||
Palladium::ThemeActive()->Get(PDColor_TextDisabled));
|
||||
LI::Layer(lrb + 1);
|
||||
LI::DrawText(NVec2(0, 37 + i * dim.y()),
|
||||
Palladium::ThemeActive()->Get(PDColor_Text2), slot);
|
||||
}
|
||||
LI::SetTextScale(tmp_txt);
|
||||
}
|
||||
|
||||
void Ovl_Ftrace::Logic() {
|
||||
if (!i_is_enabled[0]) this->Kill();
|
||||
}
|
||||
|
||||
Ovl_Metrik::Ovl_Metrik(bool* is_enabled, bool* screen, unsigned int* mt_color,
|
||||
unsigned int* txt_color, float* txt_size)
|
||||
: cpu_stats(300), gpu_stats(300) {
|
||||
i_is_enabled = is_enabled;
|
||||
i_screen = screen;
|
||||
i_mt_color = mt_color;
|
||||
i_txt_color = txt_color;
|
||||
i_txt_size = txt_size;
|
||||
v_update.Reset();
|
||||
}
|
||||
|
||||
int MetrikEntry(const std::string& text, NVec2 pos, unsigned int clr1,
|
||||
unsigned int clr2) {
|
||||
int dim_y = LI::GetTextDimensions(text).y();
|
||||
int lr = LI::Layer();
|
||||
LI::DrawRect(pos, LI::GetTextDimensions(text), clr1);
|
||||
LI::Layer(lr + 1);
|
||||
LI::DrawText(pos, clr2, text);
|
||||
LI::Layer(lr);
|
||||
return dim_y + !LI::GetFont()->IsSystemFont();
|
||||
}
|
||||
|
||||
void Graph(Palladium::Ftrace::TimeStats& s, NVec2 pos, NVec2 size, NVec2 range,
|
||||
unsigned int clr, int lod = 1) {
|
||||
float xs = static_cast<float>(size.x() / s.GetLen());
|
||||
float ys = static_cast<float>(size.y() / (range.y() - range.x()));
|
||||
|
||||
std::vector<NVec2> nodes;
|
||||
for (size_t i = 0; i < s.GetNumValues(); i += lod) {
|
||||
nodes.push_back(
|
||||
NVec2(pos.x() + i * xs, pos.y() + size.y() - (s[i] - range.x()) * ys));
|
||||
}
|
||||
for (size_t i = 1; i < nodes.size(); i++)
|
||||
LI::DrawLine(nodes[i - 1], nodes[i], clr);
|
||||
}
|
||||
|
||||
void Ovl_Metrik::Draw(void) const {
|
||||
float tmp_txt = LI::GetTextScale();
|
||||
LI::SetTextScale(*i_txt_size);
|
||||
LI::OnScreen(i_screen[0]);
|
||||
LI::NewLayer();
|
||||
std::string info = "Palladium " + std::string(PDVSTRING) + " Debug Overlay";
|
||||
float dim_y = LI::GetTextDimensions(info).y();
|
||||
mt_fps = std::format("{:.2f}ms/f -> {:.1f} FPS", Palladium::GetDeltaTime(),
|
||||
1000.f / Palladium::GetDeltaTime());
|
||||
if (pdi_idb_running) mt_fps += " IDB -> ON";
|
||||
float cpu_time = C3D_GetProcessingTime();
|
||||
cpu_stats.Add(cpu_time);
|
||||
float gpu_time = C3D_GetDrawingTime();
|
||||
gpu_stats.Add(gpu_time);
|
||||
v_update.Tick();
|
||||
if (v_update.Get() > 500.f) {
|
||||
float fps_lim = C3D_FrameRate(0.f) / 10.f;
|
||||
mt_cpu = std::format("CPU: {:.1f}% | {:.2f}ms | {:.2f}ms",
|
||||
cpu_time * fps_lim, cpu_time, cpu_stats.GetAverage());
|
||||
mt_gpu = std::format("GPU: {:.1f}% | {:.2f}ms | {:.2f}ms",
|
||||
gpu_time * fps_lim, gpu_time, gpu_stats.GetAverage());
|
||||
v_update.Reset();
|
||||
}
|
||||
mt_cmd = std::format("CMD: {:.2f}%", C3D_GetCmdBufUsage() * 100.f);
|
||||
mt_lfr = "Linear: " + Palladium::FormatBytes(linearSpaceFree());
|
||||
if (pd_flags & PDFlags_MemTrack)
|
||||
mt_mem = "Mem: " + Palladium::FormatBytes(Palladium::Memory::GetCurrent()) +
|
||||
" | " +
|
||||
Palladium::FormatBytes(Palladium::Memory::GetTotalAllocated()) +
|
||||
" | " + Palladium::FormatBytes(Palladium::Memory::GetTotalFreed());
|
||||
mt_vtx = "Vertices: " + std::to_string(LI::Vertices());
|
||||
mt_idx = "Indices: " + std::to_string(LI::Indices());
|
||||
mt_dmc = "DrawCmds: " + std::to_string(LI::DarwCommands());
|
||||
mt_drc = "DrawCalls: " + std::to_string(LI::Drawcalls());
|
||||
// Rendering
|
||||
int posy = 0;
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_FPS)
|
||||
posy += MetrikEntry(mt_fps, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
// Mod PosY to 50
|
||||
posy = 50;
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_CPU)
|
||||
posy += MetrikEntry(mt_cpu, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_GPU)
|
||||
posy += MetrikEntry(mt_gpu, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_CMD)
|
||||
posy += MetrikEntry(mt_cmd, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_LMM)
|
||||
posy += MetrikEntry(mt_lfr, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_LVT)
|
||||
posy += MetrikEntry(mt_vtx, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_LID)
|
||||
posy += MetrikEntry(mt_idx, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_LDM)
|
||||
posy += MetrikEntry(mt_dmc, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_LDC)
|
||||
posy += MetrikEntry(mt_drc, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_flags & PDFlags_MemTrack && pd_ovl_flags & PDMetrikOverlayFlags_MTD)
|
||||
posy += MetrikEntry(mt_mem, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
posy = 240 - dim_y;
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_PDO)
|
||||
posy += MetrikEntry(info, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_CGR ||
|
||||
pd_ovl_flags & PDMetrikOverlayFlags_GGR) {
|
||||
LI::NewLayer();
|
||||
float tl = 1000.f / GetFps();
|
||||
std::string tlt = std::format("{:.2f}ms", tl);
|
||||
auto tldim = LI::GetTextDimensions(tlt);
|
||||
LI::DrawRect(NVec2(0, 17), NVec2(150 + tldim.x(), 33), i_mt_color[0]);
|
||||
LI::NewLayer();
|
||||
LI::DrawText(NVec2(150, 17), i_txt_color[0], tlt);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_CGR)
|
||||
Graph(cpu_stats, NVec2(0, 17), NVec2(150, 33), NVec2(0, tl), 0xff0000ff,
|
||||
2);
|
||||
if (pd_ovl_flags & PDMetrikOverlayFlags_GGR)
|
||||
Graph(gpu_stats, NVec2(0, 17), NVec2(150, 33), NVec2(0, tl), 0xffff0000,
|
||||
2);
|
||||
}
|
||||
// Force Bottom (Debug Touchpos)
|
||||
LI::OnScreen(true);
|
||||
if (Hid::IsEvent("touch", Hid::Held)) {
|
||||
LI::DrawLine(NVec2((int)Hid::GetTouchPosition().x(), 0),
|
||||
NVec2((int)Hid::GetTouchPosition().x(), 240),
|
||||
Palladium::Color::Hex("#ff0000"));
|
||||
LI::DrawLine(NVec2(0, (int)Hid::GetTouchPosition().y()),
|
||||
NVec2(320, (int)Hid::GetTouchPosition().y()),
|
||||
Palladium::Color::Hex("#ff0000"));
|
||||
}
|
||||
LI::SetTextScale(tmp_txt);
|
||||
}
|
||||
|
||||
void Ovl_Metrik::Logic() {
|
||||
if (!i_is_enabled[0]) this->Kill();
|
||||
}
|
||||
|
||||
Ovl_Keyboard::Ovl_Keyboard(std::string& ref, PDKeyboardState& state,
|
||||
const std::string& hint, PDKeyboard type,
|
||||
PDKeyboardFlags flags) {
|
||||
// Blocks All Input outside of Keyboard
|
||||
// Doesnt work for Hidkeys down etc
|
||||
if (flags & PDKeyboardFlags_LockControls) Palladium::Hid::Lock();
|
||||
typed_text = &ref;
|
||||
this->state = &state;
|
||||
this->type = type;
|
||||
this->flags = flags;
|
||||
*this->state = PDKeyboardState_None;
|
||||
str_bak = ref;
|
||||
ft3 = 0;
|
||||
}
|
||||
|
||||
Ovl_Keyboard::~Ovl_Keyboard() {
|
||||
// And Unlock when closing Keyboard lol
|
||||
if (flags & PDKeyboardFlags_LockControls) Palladium::Hid::Unlock();
|
||||
}
|
||||
|
||||
void Ovl_Keyboard::Draw(void) const {
|
||||
float tmp_txt = LI::GetTextScale();
|
||||
LI::DefaultTextScale();
|
||||
if (ft3 > 5) {
|
||||
if (flags & PDKeyboardFlags_LockControls) Palladium::Hid::Unlock();
|
||||
}
|
||||
auto key_table =
|
||||
(type == PDKeyboard_Numpad) ? keyboard_layout_num : keyboard_layout;
|
||||
if (mode == 1)
|
||||
key_table = keyboard_layout_caps;
|
||||
else if (mode == 2)
|
||||
key_table = keyboard_layout_shift;
|
||||
if (flags & PDKeyboardFlags_BlendTop) {
|
||||
LI::OnScreen(false);
|
||||
LI::NewLayer();
|
||||
LI::DrawRect(NVec2(0, 0), NVec2(400, 240),
|
||||
Palladium::Color::RGBA(PDColor_FrameBg).changeA(150).toRGBA());
|
||||
}
|
||||
LI::OnScreen(true);
|
||||
LI::NewLayer();
|
||||
if (flags & PDKeyboardFlags_BlendBottom) {
|
||||
LI::DrawRect(NVec2(0, 0), NVec2(320, 112),
|
||||
Palladium::Color::RGBA(PDColor_FrameBg).changeA(150).toRGBA());
|
||||
}
|
||||
LI::DrawRect(NVec2(0, 112), NVec2(320, 128),
|
||||
ThemeActive()->Get(PDColor_FrameBg));
|
||||
LI::DrawRect(NVec2(0, 112), NVec2(320, 20),
|
||||
ThemeActive()->Get(PDColor_Header));
|
||||
LI::NewLayer();
|
||||
LI::DrawText(
|
||||
NVec2(5, 114),
|
||||
ThemeActive()->Get(Palladium::ThemeActive()->AutoText(PDColor_Header)),
|
||||
"> " + *typed_text);
|
||||
int lr = LI::Layer();
|
||||
for (auto const& it : key_table) {
|
||||
NVec2 szs = it.size;
|
||||
NVec2 pos = it.pos;
|
||||
NVec2 txtdim = LI::GetTextDimensions(it.disp);
|
||||
PDColor btn = PDColor_Button;
|
||||
if (Palladium::Hid::IsEvent("cancel", Palladium::Hid::Up)) {
|
||||
Palladium::Hid::Clear();
|
||||
shared_data[0x05] = 1;
|
||||
}
|
||||
if (Palladium::Hid::IsEvent("touch", Palladium::Hid::Up) &&
|
||||
UI7_InBox(Palladium::Hid::GetLastTouchPosition(), pos, szs)) {
|
||||
if (mode == 2) // Request Disable Shift
|
||||
shared_data[0x02] = 1;
|
||||
|
||||
if (it.action == 0)
|
||||
shared_data[0x01] = it.disp[0];
|
||||
else if (it.action == 1)
|
||||
shared_data[0x02] = 1;
|
||||
else if (it.action == 2)
|
||||
shared_data[0x03] = 1;
|
||||
else if (it.action == 3)
|
||||
shared_data[0x04] = 1;
|
||||
else if (it.action == 4)
|
||||
shared_data[0x05] = 1;
|
||||
else if (it.action == 5)
|
||||
shared_data[0x06] = 1;
|
||||
else if (it.action == 6)
|
||||
shared_data[0x07] = 1;
|
||||
else if (it.action == 7)
|
||||
shared_data[0x08] = 1;
|
||||
else if (it.action == 8)
|
||||
shared_data[0x09] = 1;
|
||||
} else if (Palladium::Hid::IsEvent("touch", Palladium::Hid::Held) &&
|
||||
UI7_InBox(Palladium::Hid::GetTouchPosition(), it.pos, it.size)) {
|
||||
btn = PDColor_ButtonHovered;
|
||||
pos -= NVec2(1, 1);
|
||||
szs += NVec2(2, 2);
|
||||
}
|
||||
NVec2 txtpos = NVec2(pos.x() + szs.x() * 0.5 - txtdim.x() * 0.5,
|
||||
pos.y() + szs.y() * 0.5 - txtdim.y() * 0.5);
|
||||
LI::Layer(lr);
|
||||
LI::DrawRect(pos, szs, ThemeActive()->Get(btn));
|
||||
LI::Layer(lr + 1);
|
||||
LI::DrawText(txtpos,
|
||||
ThemeActive()->Get(Palladium::ThemeActive()->AutoText(btn)),
|
||||
it.disp);
|
||||
}
|
||||
if (ft3 > 5) {
|
||||
if (flags & PDKeyboardFlags_LockControls) Palladium::Hid::Lock();
|
||||
}
|
||||
LI::SetTextScale(tmp_txt);
|
||||
}
|
||||
|
||||
void Ovl_Keyboard::Logic() {
|
||||
ft3++;
|
||||
for (const auto& it : shared_data) {
|
||||
if (it.first == 0x01) {
|
||||
typed_text->push_back(it.second);
|
||||
} else if (it.first == 0x02) {
|
||||
// Shift
|
||||
mode = (mode == 2) ? 0 : 2;
|
||||
} else if (it.first == 0x03) {
|
||||
if (typed_text->length() >= 1)
|
||||
typed_text->erase(typed_text->begin() + typed_text->length() - 1);
|
||||
} else if (it.first == 0x04) {
|
||||
// Enter
|
||||
} else if (it.first == 0x05) {
|
||||
*typed_text = str_bak;
|
||||
*state = PDKeyboardState_Cancel;
|
||||
this->Kill();
|
||||
} else if (it.first == 0x06) {
|
||||
*state = PDKeyboardState_Confirm;
|
||||
this->Kill();
|
||||
} else if (it.first == 0x07) {
|
||||
// this->typed_text += '\t'; // Tab
|
||||
} else if (it.first == 0x08) {
|
||||
// Caps
|
||||
mode = (mode == 1) ? 0 : 1;
|
||||
} else if (it.first == 0x09) {
|
||||
typed_text->append(" "); // Space
|
||||
}
|
||||
}
|
||||
|
||||
shared_data.clear();
|
||||
}
|
||||
} // namespace Palladium
|
@ -1,460 +0,0 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <pd/ResultDecoder.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
#include <sstream>
|
||||
|
||||
static std::map<int, std::string> modules = {
|
||||
{0, "common"},
|
||||
{1, "kernel"},
|
||||
{2, "util"},
|
||||
{3, "file server"},
|
||||
{4, "loader server"},
|
||||
{5, "tcb"},
|
||||
{6, "os"},
|
||||
{7, "dbg"},
|
||||
{8, "dmnt"},
|
||||
{9, "pdn"},
|
||||
{10, "gsp"},
|
||||
{11, "i2c"},
|
||||
{12, "gpio"},
|
||||
{13, "dd"},
|
||||
{14, "codec"},
|
||||
{15, "spi"},
|
||||
{16, "pxi"},
|
||||
{17, "fs"},
|
||||
{18, "di"},
|
||||
{19, "hid"},
|
||||
{20, "cam"},
|
||||
{21, "pi"},
|
||||
{22, "pm"},
|
||||
{23, "pm_low"},
|
||||
{24, "fsi"},
|
||||
{25, "srv"},
|
||||
{26, "ndm"},
|
||||
{27, "nwm"},
|
||||
{28, "soc"},
|
||||
{29, "ldr"},
|
||||
{30, "acc"},
|
||||
{31, "romfs"},
|
||||
{32, "am"},
|
||||
{33, "hio"},
|
||||
{34, "updater"},
|
||||
{35, "mic"},
|
||||
{36, "fnd"},
|
||||
{37, "mp"},
|
||||
{38, "mpwl"},
|
||||
{39, "ac"},
|
||||
{40, "http"},
|
||||
{41, "dsp"},
|
||||
{42, "snd"},
|
||||
{43, "dlp"},
|
||||
{44, "hio_low"},
|
||||
{45, "csnd"},
|
||||
{46, "ssl"},
|
||||
{47, "am_low"},
|
||||
{48, "nex"},
|
||||
{49, "friends"},
|
||||
{50, "rdt"},
|
||||
{51, "applet"},
|
||||
{52, "nim"},
|
||||
{53, "ptm"},
|
||||
{54, "midi"},
|
||||
{55, "mc"},
|
||||
{56, "swc"},
|
||||
{57, "fatfs"},
|
||||
{58, "ngc"},
|
||||
{59, "card"},
|
||||
{60, "cardnor"},
|
||||
{61, "sdmc"},
|
||||
{62, "boss"},
|
||||
{63, "dbm"},
|
||||
{64, "config"},
|
||||
{65, "ps"},
|
||||
{66, "cec"},
|
||||
{67, "ir"},
|
||||
{68, "uds"},
|
||||
{69, "pl"},
|
||||
{70, "cup"},
|
||||
{71, "gyroscope"},
|
||||
{72, "mcu"},
|
||||
{73, "ns"},
|
||||
{74, "news"},
|
||||
{75, "ro"},
|
||||
{76, "gd"},
|
||||
{77, "card spi"},
|
||||
{78, "ec"},
|
||||
{79, "web browser"},
|
||||
{80, "test"},
|
||||
{81, "enc"},
|
||||
{82, "pia"},
|
||||
{83, "act"},
|
||||
{84, "vctl"},
|
||||
{85, "olv"},
|
||||
{86, "neia"},
|
||||
{87, "npns"},
|
||||
{90, "avd"},
|
||||
{91, "l2b"},
|
||||
{92, "mvd"},
|
||||
{93, "nfc"},
|
||||
{94, "uart"},
|
||||
{95, "spm"},
|
||||
{96, "qtm"},
|
||||
{97, "nfp"},
|
||||
{254, "application"},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> levels = {
|
||||
{0, "Success"}, {1, "Info"}, {25, "Status"},
|
||||
{26, "Temporary"}, {27, "Permanent"}, {28, "Usage"},
|
||||
{29, "Reinitialize"}, {30, "Reset"}, {31, "Fatal"},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> summaries = {
|
||||
{0, "Success"},
|
||||
{1, "Nothing happened"},
|
||||
{2, "Would block"},
|
||||
{3, "Out of resource"},
|
||||
{4, "Not found"},
|
||||
{5, "Invalid state"},
|
||||
{6, "Not supported"},
|
||||
{7, "Invalid argument"},
|
||||
{8, "Wrong argument"},
|
||||
{9, "Canceled"},
|
||||
{10, "Status changed"},
|
||||
{11, "Internal"},
|
||||
{63, "Invalid result value"},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> desccommon = {
|
||||
{0, "Success"},
|
||||
{1000, "Invalid selection"},
|
||||
{1001, "Too large"},
|
||||
{1002, "Not authorized"},
|
||||
{1003, "Already done"},
|
||||
{1004, "Invalid size"},
|
||||
{1005, "Invalid enum value"},
|
||||
{1006, "Invalid combination"},
|
||||
{1007, "No data"},
|
||||
{1008, "Busy"},
|
||||
{1009, "Misaligned address"},
|
||||
{1010, "Misaligned size"},
|
||||
{1011, "Out of memory"},
|
||||
{1012, "Not implemented"},
|
||||
{1013, "Invalid address"},
|
||||
{1014, "Invalid pointer"},
|
||||
{1015, "Invalid handle"},
|
||||
{1016, "Not initialized"},
|
||||
{1017, "Already initialized"},
|
||||
{1018, "Not found"},
|
||||
{1019, "Cancel requested"},
|
||||
{1020, "Already exists"},
|
||||
{1021, "Out of range"},
|
||||
{1022, "Timeout"},
|
||||
{1023, "Invalid result value"},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> desckernel = {
|
||||
{2, "Invalid memory permissions."},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> descos = {
|
||||
{10, "Not enough memory."},
|
||||
{26, "Session closed by remote."},
|
||||
{47, "Invalid command header."},
|
||||
};
|
||||
|
||||
// Need to Fix The Range based Values
|
||||
static std::map<int, std::string> descfs = {
|
||||
{101, "Archive not mounted or mount-point not found."},
|
||||
{120, "Title or object not found."},
|
||||
{141, "Gamecard not inserted."},
|
||||
{230, "Invalid open flags or permissions."},
|
||||
{391, "NCCH hash check failed."},
|
||||
{302, "RSA or AES-MAC verification failed."},
|
||||
{395, "RomFS or Savedata hash check failed."},
|
||||
{630, "Command not allowed, or missing permissions."},
|
||||
{702, "Invalid path."},
|
||||
{761, "Incorrect ExeFS read size."},
|
||||
{100, "[Media] not found."},
|
||||
{180, "Exists already."},
|
||||
{200, "Not enough space."},
|
||||
{220, "Invalidated archive."},
|
||||
{230, "Unacceptable or write protected."},
|
||||
{340, "0x01"},
|
||||
{360, "Bad format."},
|
||||
{390, "Verification failure."},
|
||||
{400, "0x01"},
|
||||
{600, "Out of resources."},
|
||||
{630, "Access denied."},
|
||||
{661, "0x01"},
|
||||
{700, "Invalid argument."},
|
||||
{730, "Not initialized."},
|
||||
{750, "Already initialized."},
|
||||
{760, "Not supported."},
|
||||
{780, "0x01"},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> descsrv = {
|
||||
{5,
|
||||
"Invalid string length (service name length is zero or longer than 8 "
|
||||
"chars)."},
|
||||
{6,
|
||||
"Access to service denied (requested a service the application does "
|
||||
"not have access to)."},
|
||||
{7,
|
||||
"String size does not match contents (service name contains unexpected "
|
||||
"null byte)."},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> descnwm = {
|
||||
{2,
|
||||
"This error usually indicates the wifi chipset in the console is dying "
|
||||
"or dead."},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> descam = {
|
||||
{4, "Invalid ticket version."},
|
||||
{32, "Empty CIA."},
|
||||
{37, "Invalid NCCH."},
|
||||
{39, "Invalid title version."},
|
||||
{43, "Database doesn\"t exist, or it failed to open."},
|
||||
{44, "Trying to uninstall system-app."},
|
||||
{106,
|
||||
"Invalid signature/CIA. Usually happens when developer UNITINFO is "
|
||||
"enabled in Luma3DS."},
|
||||
{393, "Invalid database."},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> deschttp = {
|
||||
{105, "Request timed out."},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> descnim = {
|
||||
{1,
|
||||
"Invalid string IPC paramater (non null terminated at its indicated "
|
||||
"length)."},
|
||||
{12,
|
||||
"Invalid country code returned by CFG module reading config save "
|
||||
"0xB0000."},
|
||||
{13,
|
||||
"Zero string length console serial number or '000000000000000' "
|
||||
"returned by CFG's SecureInfoGetSerialNo."},
|
||||
{18,
|
||||
"General data reading error of NIM's .dat files from its system save, "
|
||||
"bad data or bad data lengths."},
|
||||
{22,
|
||||
"General invalid data or length of data returned from nintendo "
|
||||
"servers. (Only applicable for some operations)"},
|
||||
{25,
|
||||
"IntegrityVerificationSeed is waiting on servers to be synced into "
|
||||
"console. Can't processed with online services without sync being "
|
||||
"completed first over IPC request."},
|
||||
{26,
|
||||
"Unavailable/unaccessable IntegrityVerificationSeed on Nintendo "
|
||||
"servers. May happen if NIM is told to import "
|
||||
"IntegrityVerificationSeed from servers at any time other than after "
|
||||
"the successful System Transfer reboot."},
|
||||
{27,
|
||||
"Invalid country language code returned by CFG module reading config "
|
||||
"save 0xA0002."},
|
||||
{37,
|
||||
"Service is in Standby Mode. (eShop ban? General service is down? "
|
||||
"This caused by a server response flag on account information. "
|
||||
"Account is not referring to NNID.)"},
|
||||
{39, "HTTP Status non 200. (Only applicable for some operations)"},
|
||||
{40, "General XML read/write error while processing Auto Delivery XMLs."},
|
||||
{41,
|
||||
"General XML read/write error while processing Auto Delivery XMLs. "
|
||||
"(Stubbed virtual call was called)"},
|
||||
{58,
|
||||
"Invalid NPNS token returned by CFG module reading config save 0xF0006."},
|
||||
{67, "HTTP Status 404 while trying to download a game's seed."},
|
||||
{68, "HTTP Status 503 while trying to download a game's seed."},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> descmvd = {
|
||||
{271, "Invalid configuration."},
|
||||
};
|
||||
|
||||
static std::map<int, std::string> descqtm = {
|
||||
{8, "Camera is already in use or busy."},
|
||||
};
|
||||
|
||||
// Need to Fix The Range based Values
|
||||
static std::map<int, std::string> descapplication = {
|
||||
{0,
|
||||
"The application raised an error. Please consult the application's "
|
||||
"source code or ask the author for assistance with it."},
|
||||
{1024, "0x01"},
|
||||
};
|
||||
|
||||
namespace Palladium {
|
||||
void ResultDecoder::Load(Result rescode) { this->m_rescode = rescode; }
|
||||
void ResultDecoder::Load(std::string rescode) {
|
||||
std::stringstream ss;
|
||||
ss << rescode;
|
||||
ss >> std::hex >> this->m_rescode;
|
||||
}
|
||||
std::string Palladium::ResultDecoder::GetCode() {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << m_rescode;
|
||||
std::string reshex(ss.str());
|
||||
return reshex;
|
||||
}
|
||||
std::string ResultDecoder::GetLevel() {
|
||||
std::string res = levels.at(this->GetLevelInt()) + " (" +
|
||||
std::to_string(this->GetLevelInt()) + ")";
|
||||
return res;
|
||||
}
|
||||
int ResultDecoder::GetLevelInt() { return R_LEVEL(m_rescode); }
|
||||
std::string ResultDecoder::GetModule() {
|
||||
std::string res = modules.at(this->GetModuleInt()) + " (" +
|
||||
std::to_string(this->GetModuleInt()) + ")";
|
||||
return res;
|
||||
}
|
||||
int ResultDecoder::GetModuleInt() { return R_MODULE(m_rescode); }
|
||||
std::string ResultDecoder::GetDescription() {
|
||||
std::string res = "Desc Not Implemented!";
|
||||
switch (this->GetModuleInt()) {
|
||||
case 0:
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
break;
|
||||
case 1:
|
||||
if ((desckernel.find(this->GetDescriptionInt()) == desckernel.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = desckernel.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if ((descos.find(this->GetDescriptionInt()) == descos.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descos.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
if ((descfs.find(this->GetDescriptionInt()) == descfs.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descfs.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 25:
|
||||
if ((descsrv.find(this->GetDescriptionInt()) == descsrv.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descsrv.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
if ((descnwm.find(this->GetDescriptionInt()) == descnwm.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descnwm.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
if ((descam.find(this->GetDescriptionInt()) == descam.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descam.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
if ((deschttp.find(this->GetDescriptionInt()) == deschttp.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = deschttp.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 52:
|
||||
if ((descnim.find(this->GetDescriptionInt()) == descnim.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descnim.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 92:
|
||||
if ((descmvd.find(this->GetDescriptionInt()) == descmvd.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descmvd.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 96:
|
||||
if ((descqtm.find(this->GetDescriptionInt()) == descqtm.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descqtm.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
case 254:
|
||||
if ((descapplication.find(this->GetDescriptionInt()) ==
|
||||
descapplication.end())) {
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
} else {
|
||||
res = descapplication.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
res = desccommon.at(this->GetDescriptionInt()) + " (" +
|
||||
std::to_string(this->GetDescriptionInt()) + ")";
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
int ResultDecoder::GetDescriptionInt() { return R_DESCRIPTION(m_rescode); }
|
||||
std::string ResultDecoder::GetSummary() {
|
||||
std::string res = summaries.at(this->GetSummaryInt()) + " (" +
|
||||
std::to_string(this->GetSummaryInt()) + ")";
|
||||
return res;
|
||||
}
|
||||
|
||||
void Palladium::ResultDecoder::WriteLog() {
|
||||
std::string out_path = "sdmc:/Palladium/Apps/" + pdi_app_name + "/resdec";
|
||||
std::filesystem::create_directories(out_path);
|
||||
out_path += "/err_result_" + std::to_string(time(0)) + ".log";
|
||||
std::ofstream out(out_path, std::ios::app);
|
||||
out << "+-------------------\n";
|
||||
out << "| Error: " << GetCode() << "\n";
|
||||
out << "+-------------------\n";
|
||||
out << "| Module: " << GetModule() << "\n";
|
||||
out << "+-------------------\n";
|
||||
out << "| Level: " << GetLevel() << "\n";
|
||||
out << "+-------------------\n";
|
||||
out << "| Summary: " << GetSummary() << "\n";
|
||||
out << "+-------------------\n";
|
||||
out << "| Description: " << GetDescription() << "\n";
|
||||
out << "+-------------------\n";
|
||||
out.close();
|
||||
}
|
||||
|
||||
int ResultDecoder::GetSummaryInt() { return R_SUMMARY(m_rescode); }
|
||||
} // namespace Palladium
|
@ -1,124 +0,0 @@
|
||||
#include <pd/external/stb_image.h>
|
||||
|
||||
#include <pd/Rubidium.hpp>
|
||||
#include <pd/base/Color.hpp>
|
||||
|
||||
void d7_pixel_blend(Palladium::Rubidium* rb, int x, int y, unsigned int clr,
|
||||
float blend) {
|
||||
Palladium::Color::RGBA cl(clr);
|
||||
cl.fade_to(Palladium::Color::RGBA(0.f, 0.f, 0.f, 1.f), blend);
|
||||
rb->DrawPixel(x, y, cl.toRGBA());
|
||||
}
|
||||
|
||||
namespace Palladium {
|
||||
Rubidium::Rubidium(int w, int h) { image = Palladium::nimg(w, h); }
|
||||
Rubidium::Rubidium() { image = Palladium::nimg(1, 1); }
|
||||
|
||||
Rubidium::~Rubidium() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void Rubidium::LoadFile(const std::string& path) {
|
||||
int w, h, c;
|
||||
uint8_t* dat = stbi_load(path.c_str(), &w, &h, &c, 4);
|
||||
image = nimg(w, h);
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int pos = (y * w + x) * 4;
|
||||
image.pixel_buffer[pos + 0] = dat[pos + 0];
|
||||
image.pixel_buffer[pos + 1] = dat[pos + 1];
|
||||
image.pixel_buffer[pos + 2] = dat[pos + 2];
|
||||
image.pixel_buffer[pos + 3] = dat[pos + 3];
|
||||
}
|
||||
}
|
||||
stbi_image_free(dat);
|
||||
}
|
||||
|
||||
void Rubidium::LoadNimg(const std::string& path) {
|
||||
image = Palladium::NIMG_Load(path);
|
||||
}
|
||||
|
||||
void Rubidium::DrawPixel(int x, int y, unsigned int color) {
|
||||
if (x > image.width || x < 0 || y > image.height || y < 0) return;
|
||||
Palladium::Color::RGBA splitter(color);
|
||||
image.pixel_buffer[((y * image.width + x) * 4) + 0] = splitter.m_r;
|
||||
image.pixel_buffer[((y * image.width + x) * 4) + 1] = splitter.m_g;
|
||||
image.pixel_buffer[((y * image.width + x) * 4) + 2] = splitter.m_b;
|
||||
image.pixel_buffer[((y * image.width + x) * 4) + 3] = splitter.m_a;
|
||||
}
|
||||
|
||||
void Rubidium::DrawRect(int x, int y, int w, int h, unsigned int color, int t) {
|
||||
DrawLine(x, y, x + w, y, color, t);
|
||||
DrawLine(x, y, x, y + h, color, t);
|
||||
DrawLine(x, y + h, x + w, y + h, color, t);
|
||||
DrawLine(x + w, y, x + w, y + h, color, t);
|
||||
}
|
||||
|
||||
void Rubidium::DrawRectSolid(int x, int y, int w, int h, unsigned int color) {
|
||||
for (int ix = x; ix < x + w; ix++) {
|
||||
for (int iy = y; iy < y + h; iy++) {
|
||||
DrawPixel(ix, iy, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rubidium::DrawLine(int x1, int y1, int x2, int y2, unsigned int color,
|
||||
int t) {
|
||||
// Reference
|
||||
// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
|
||||
int dx = abs(x2 - x1);
|
||||
int dy = abs(y2 - y1);
|
||||
int sx = (x1 < x2) ? 1 : -1;
|
||||
int sy = (y1 < y2) ? 1 : -1;
|
||||
int err = dx - dy;
|
||||
int ht = t / 2;
|
||||
while (true) {
|
||||
for (int i = -ht; i <= ht; i++) {
|
||||
if (dy <= dx) {
|
||||
DrawPixel(x1, y1 + i, color);
|
||||
} else {
|
||||
DrawPixel(x1 + i, y1, color);
|
||||
}
|
||||
}
|
||||
if (x1 == x2 && y1 == y2) break;
|
||||
int e2 = err * 2;
|
||||
if (e2 > -dy) {
|
||||
err -= dy;
|
||||
x1 += sx;
|
||||
}
|
||||
if (e2 < dx) {
|
||||
err += dx;
|
||||
y1 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rubidium::Flip(bool h, bool v) {
|
||||
const nimg _bak = image;
|
||||
if (h) {
|
||||
for (int x = 0; x < image.width; x++) {
|
||||
for (int y = 0; y < image.height; y++) {
|
||||
int src = (y * image.width + x) * 4;
|
||||
int dst = ((image.height - 1 - y) * image.width + x) * 4;
|
||||
image.pixel_buffer[src + 0] = _bak.pixel_buffer[dst + 0];
|
||||
image.pixel_buffer[src + 1] = _bak.pixel_buffer[dst + 1];
|
||||
image.pixel_buffer[src + 2] = _bak.pixel_buffer[dst + 2];
|
||||
image.pixel_buffer[src + 3] = _bak.pixel_buffer[dst + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v) {
|
||||
for (int x = 0; x < image.width; x++) {
|
||||
for (int y = 0; y < image.height; y++) {
|
||||
int src = (y * image.width + x) * 4;
|
||||
int dst = (y * image.width + (image.width - 1 - x)) * 4;
|
||||
image.pixel_buffer[src + 0] = _bak.pixel_buffer[dst + 0];
|
||||
image.pixel_buffer[src + 1] = _bak.pixel_buffer[dst + 1];
|
||||
image.pixel_buffer[src + 2] = _bak.pixel_buffer[dst + 2];
|
||||
image.pixel_buffer[src + 3] = _bak.pixel_buffer[dst + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Palladium
|
@ -1,51 +0,0 @@
|
||||
#include <3ds.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <pd/Sheet.hpp>
|
||||
|
||||
namespace Palladium {
|
||||
void Sheet::LoadT3X(const std::string& path) {
|
||||
if (sheet_tex) {
|
||||
C3D_TexDelete(sheet_tex);
|
||||
delete sheet_tex;
|
||||
sheet_tex = nullptr;
|
||||
}
|
||||
sheet_tex = new C3D_Tex;
|
||||
std::fstream f(path, std::ios::in | std::ios::binary);
|
||||
if (!f) {
|
||||
delete sheet_tex;
|
||||
sheet_tex = nullptr;
|
||||
return;
|
||||
}
|
||||
f.seekg(0, std::ios::end);
|
||||
std::vector<unsigned char> dat(f.tellg());
|
||||
f.seekg(0, std::ios::beg);
|
||||
f.read(reinterpret_cast<char*>(dat.data()), dat.size());
|
||||
sheet =
|
||||
Tex3DS_TextureImport(dat.data(), dat.size(), sheet_tex, nullptr, true);
|
||||
C3D_TexSetFilter(sheet_tex, GPU_LINEAR, GPU_LINEAR);
|
||||
f.close();
|
||||
int st = Tex3DS_GetNumSubTextures(sheet);
|
||||
sprites.resize(st);
|
||||
for (int i = 0; i < st; i++) {
|
||||
sprites[i] = Texture::New();
|
||||
auto stex = Tex3DS_GetSubTexture(sheet, i);
|
||||
sprites[i]->ExternalLoad(
|
||||
sheet_tex, NVec2(stex->width, stex->height),
|
||||
NVec4(stex->left, stex->top, stex->right, stex->bottom));
|
||||
sprites[i]->AutoDelete(false);
|
||||
}
|
||||
}
|
||||
|
||||
Texture::Ref Sheet::Get(int idx) {
|
||||
if (idx < 0 || idx >= (int)sprites.size()) return nullptr;
|
||||
return sprites[idx];
|
||||
}
|
||||
|
||||
Image::Ref Sheet::GetImage(int idx) {
|
||||
if (idx < 0 || idx >= (int)sprites.size()) return nullptr;
|
||||
Image::Ref img = Image::New();
|
||||
img->Set(sprites[idx], sprites[idx]->GetUV());
|
||||
return img;
|
||||
}
|
||||
} // namespace Palladium
|
129
source/Sound.cpp
129
source/Sound.cpp
@ -1,129 +0,0 @@
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <pd/Sound.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
// Reference: http://yannesposito.com/Scratch/en/blog/2010-10-14-Fun-with-wav/
|
||||
typedef struct _WavHeader {
|
||||
char magic[4]; // "RIFF"
|
||||
u32 totallength; // Total file length, minus 8.
|
||||
char wavefmt[8]; // Should be "WAVEfmt "
|
||||
u32 format; // 16 for PCM format
|
||||
u16 pcm; // 1 for PCM format
|
||||
u16 channels; // Channels
|
||||
u32 frequency; // Sampling frequency
|
||||
u32 bytes_per_second;
|
||||
u16 bytes_by_capture;
|
||||
u16 bits_per_sample;
|
||||
char data[4]; // "data"
|
||||
u32 bytes_in_data;
|
||||
} WavHeader;
|
||||
static_assert(sizeof(WavHeader) == 44, "WavHeader size is not 44 bytes.");
|
||||
|
||||
using namespace Palladium;
|
||||
Sound::Sound(const string &path, int channel, bool toloop) {
|
||||
if (pdi_is_ndsp) {
|
||||
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
|
||||
ndspSetOutputCount(2); // Num of buffers
|
||||
|
||||
// Reading wav file
|
||||
std::fstream fp(path, std::ios::in | std::ios::binary);
|
||||
|
||||
if (!fp.is_open()) {
|
||||
return;
|
||||
}
|
||||
|
||||
WavHeader wavHeader;
|
||||
fp.read(reinterpret_cast<char *>(&wavHeader), sizeof(WavHeader));
|
||||
size_t read = fp.tellg();
|
||||
if (read != sizeof(wavHeader)) {
|
||||
// Short read.
|
||||
fp.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify the header.
|
||||
static const char RIFF_magic[4] = {'R', 'I', 'F', 'F'};
|
||||
if (memcmp(wavHeader.magic, RIFF_magic, sizeof(wavHeader.magic)) != 0) {
|
||||
// Incorrect magic number.
|
||||
fp.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (wavHeader.totallength == 0 ||
|
||||
(wavHeader.channels != 1 && wavHeader.channels != 2) ||
|
||||
(wavHeader.bits_per_sample != 8 && wavHeader.bits_per_sample != 16)) {
|
||||
// Unsupported WAV file.
|
||||
fp.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the file size.
|
||||
fp.seekg(0, std::ios::end);
|
||||
dataSize = fp.tellg();
|
||||
dataSize -= sizeof(WavHeader);
|
||||
|
||||
// Allocating and reading samples
|
||||
data = static_cast<u8 *>(linearAlloc(dataSize));
|
||||
fp.seekg(44, std::ios::beg);
|
||||
fp.read(reinterpret_cast<char *>(data), dataSize);
|
||||
fp.close();
|
||||
dataSize /= 2; // FIXME: 16-bit or stereo?
|
||||
|
||||
// Find the right format
|
||||
u16 ndspFormat;
|
||||
if (wavHeader.bits_per_sample == 8) {
|
||||
ndspFormat = (wavHeader.channels == 1) ? NDSP_FORMAT_MONO_PCM8
|
||||
: NDSP_FORMAT_STEREO_PCM8;
|
||||
} else {
|
||||
ndspFormat = (wavHeader.channels == 1) ? NDSP_FORMAT_MONO_PCM16
|
||||
: NDSP_FORMAT_STEREO_PCM16;
|
||||
}
|
||||
|
||||
ndspChnReset(channel);
|
||||
ndspChnSetInterp(channel, NDSP_INTERP_NONE);
|
||||
ndspChnSetRate(channel, float(wavHeader.frequency));
|
||||
ndspChnSetFormat(channel, ndspFormat);
|
||||
|
||||
// Create and play a wav buffer
|
||||
memset(&waveBuf, 0, sizeof(waveBuf));
|
||||
|
||||
waveBuf.data_vaddr = reinterpret_cast<u32 *>(data);
|
||||
waveBuf.nsamples = dataSize / (wavHeader.bits_per_sample >> 3);
|
||||
waveBuf.looping = toloop;
|
||||
waveBuf.status = NDSP_WBUF_FREE;
|
||||
chnl = channel;
|
||||
}
|
||||
}
|
||||
|
||||
Sound::~Sound() {
|
||||
if (pdi_is_ndsp) {
|
||||
waveBuf.data_vaddr = 0;
|
||||
waveBuf.nsamples = 0;
|
||||
waveBuf.looping = false;
|
||||
waveBuf.status = 0;
|
||||
ndspChnWaveBufClear(chnl);
|
||||
|
||||
if (data) {
|
||||
linearFree(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sound::Play() {
|
||||
if (pdi_is_ndsp) {
|
||||
if (!data) return;
|
||||
DSP_FlushDataCache(data, dataSize);
|
||||
ndspChnWaveBufAdd(chnl, &waveBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void Sound::Stop() {
|
||||
if (pdi_is_ndsp) {
|
||||
if (!data) return;
|
||||
ndspChnWaveBufClear(chnl);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
#include <pd/Sprite.hpp>
|
||||
/*
|
||||
void Palladium::Sprite::FromSheet(Palladium::Sheet::Ref sheet, size_t index) {
|
||||
C2D_SpriteFromSheet(&this->sprite, sheet->Get(), index);
|
||||
}
|
||||
bool Palladium::Sprite::Draw() {
|
||||
// Patch Depth before draw
|
||||
sprite.params.depth = 0.5;
|
||||
return C2D_DrawSprite(&this->sprite);
|
||||
}
|
||||
void Palladium::Sprite::SetCenter(float x, float y) {
|
||||
C2D_SpriteSetCenter(&this->sprite, x, y);
|
||||
}
|
||||
void Palladium::Sprite::SetPos(float x, float y) {
|
||||
C2D_SpriteSetPos(&this->sprite, x, y);
|
||||
}
|
||||
void Palladium::Sprite::SetRotation(float rotation) {
|
||||
C2D_SpriteSetRotation(&this->sprite, rotation);
|
||||
}
|
||||
void Palladium::Sprite::Rotate(float speed) {
|
||||
C2D_SpriteRotateDegrees(&this->sprite, speed);
|
||||
}
|
||||
float Palladium::Sprite::GetHeight() { return GetSize().x; }
|
||||
float Palladium::Sprite::GetWidth() { return GetSize().y; }
|
||||
float Palladium::Sprite::GetPosX() { return GetPos().x; }
|
||||
float Palladium::Sprite::GetPosY() { return GetPos().y; }
|
||||
|
||||
NVec2 Palladium::Sprite::GetPos() {
|
||||
return NVec2(this->sprite.params.pos.x, this->sprite.params.pos.y);
|
||||
}
|
||||
|
||||
NVec2 Palladium::Sprite::GetSize() {
|
||||
return NVec2(this->sprite.params.pos.w, this->sprite.params.pos.h);
|
||||
}
|
||||
|
||||
void Palladium::Sprite::SetPos(NVec2 pos) {
|
||||
C2D_SpriteSetPos(&this->sprite, pos.x, pos.y);
|
||||
}
|
||||
|
||||
void Palladium::Sprite::SetScale(NVec2 scale) {
|
||||
C2D_SpriteScale(&this->sprite, scale.x, scale.y);
|
||||
}
|
||||
void Palladium::Sprite::SetRotCenter(NVec2 percentage) {
|
||||
C2D_SpriteSetCenter(&this->sprite, percentage.x, percentage.y);
|
||||
}
|
||||
|
||||
void Palladium::Sprite::FromImage(Palladium::Image::Ref img) {
|
||||
// C2D_SpriteFromImage(&this->sprite, img->Get());
|
||||
}
|
||||
|
||||
void Palladium::Sprite::SetScale(float x, float y) {
|
||||
C2D_SpriteScale(&this->sprite, x, y);
|
||||
}*/
|
@ -1,22 +0,0 @@
|
||||
#include <memory>
|
||||
#include <pd/Tasks.hpp>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
static std::vector<std::shared_ptr<std::thread>> threads;
|
||||
|
||||
int Palladium::Tasks::Create(std::function<void()> fun) {
|
||||
auto thrd = std::make_shared<std::thread>(fun);
|
||||
threads.push_back(thrd);
|
||||
return threads.size();
|
||||
}
|
||||
|
||||
void Palladium::Tasks::DestroyAll() {
|
||||
for (auto& it : threads) {
|
||||
if (it && it->joinable()) {
|
||||
it->join();
|
||||
}
|
||||
}
|
||||
// Delete Pointers
|
||||
threads.clear();
|
||||
}
|
@ -1,243 +0,0 @@
|
||||
#include <pd/external/stb_image.h>
|
||||
#include <pd/external/stb_image_write.h>
|
||||
|
||||
#include <pd/Error.hpp>
|
||||
#include <pd/Texture.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
|
||||
namespace pdi {
|
||||
static bool single_bit(unsigned int v) { return v && !(v & (v - 1)); }
|
||||
static u32 get_pow2(u32 v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return (v >= 64 ? v : 64);
|
||||
}
|
||||
|
||||
static void RGB24toRGBA32(std::vector<uint8_t> &out,
|
||||
const std::vector<uint8_t> &in, const int &w,
|
||||
const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int src = (y * w + x) * 3;
|
||||
int dst = (y * w + x) * 4;
|
||||
out[dst + 0] = in[src + 0];
|
||||
out[dst + 1] = in[src + 1];
|
||||
out[dst + 2] = in[src + 2];
|
||||
out[dst + 3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace pdi
|
||||
|
||||
namespace Palladium {
|
||||
GPU_TEXCOLOR GetTexFmt(Texture::Type type) {
|
||||
if (type == Texture::RGBA32)
|
||||
return GPU_RGBA8;
|
||||
else if (type == Texture::RGB24)
|
||||
return GPU_RGB8;
|
||||
else if (type == Texture::A8)
|
||||
return GPU_A8;
|
||||
return GPU_RGBA8; // Default
|
||||
}
|
||||
int GetBPP(Texture::Type type) {
|
||||
if (type == Texture::RGBA32)
|
||||
return 4;
|
||||
else if (type == Texture::RGB24)
|
||||
return 3;
|
||||
else if (type == Texture::A8)
|
||||
return 1;
|
||||
return 0; // Error
|
||||
}
|
||||
void Texture::MakeTex(std::vector<unsigned char> &buf, int w, int h, Type type,
|
||||
Filter filter) {
|
||||
if (!tex) {
|
||||
return;
|
||||
}
|
||||
// Don't check here as check done before
|
||||
int bpp = GetBPP(type);
|
||||
if (bpp == 4) {
|
||||
//// RGBA -> Abgr
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int pos = (x + y * w) * bpp;
|
||||
auto r = buf[pos + 0];
|
||||
auto g = buf[pos + 1];
|
||||
auto b = buf[pos + 2];
|
||||
auto a = buf[pos + 3];
|
||||
buf[pos + 0] = a;
|
||||
buf[pos + 1] = b;
|
||||
buf[pos + 2] = g;
|
||||
buf[pos + 3] = r;
|
||||
}
|
||||
}
|
||||
} else if (bpp == 3) {
|
||||
// RGBA -> Abgr
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int pos = (x + y * w) * bpp;
|
||||
auto r = buf[pos + 0];
|
||||
auto g = buf[pos + 1];
|
||||
auto b = buf[pos + 2];
|
||||
buf[pos + 0] = b;
|
||||
buf[pos + 1] = g;
|
||||
buf[pos + 2] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NVec2 tex_size(w, h);
|
||||
// Pow2
|
||||
if (!pdi::single_bit(w)) tex_size.x() = pdi::get_pow2((unsigned int)w);
|
||||
if (!pdi::single_bit(h)) tex_size.y() = pdi::get_pow2((unsigned int)h);
|
||||
|
||||
this->img_size.x() = (u16)w;
|
||||
this->img_size.y() = (u16)h;
|
||||
this->uvs.x() = 0.0f;
|
||||
this->uvs.y() = 1.0f;
|
||||
this->uvs.z() = ((float)w / (float)tex_size.x());
|
||||
this->uvs.w() = 1.0 - ((float)h / (float)tex_size.y());
|
||||
|
||||
// Texture Setup
|
||||
auto fltr = (filter == NEAREST ? GPU_NEAREST : GPU_LINEAR);
|
||||
auto tex_fmt = GetTexFmt(type);
|
||||
C3D_TexInit(tex, (u16)tex_size.x(), (u16)tex_size.y(), tex_fmt);
|
||||
C3D_TexSetFilter(tex, fltr, fltr);
|
||||
|
||||
memset(tex->data, 0, tex->size);
|
||||
|
||||
if (bpp == 3 || bpp == 4) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int dst_pos = ((((y >> 3) * ((int)tex_size.x() >> 3) + (x >> 3)) << 6) +
|
||||
((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) |
|
||||
((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) *
|
||||
bpp;
|
||||
int src_pos = (y * w + x) * bpp;
|
||||
|
||||
memcpy(&((unsigned char *)tex->data)[dst_pos], &buf[src_pos], bpp);
|
||||
}
|
||||
}
|
||||
C3D_TexFlush(tex);
|
||||
} else if (bpp == 1) {
|
||||
C3D_TexLoadImage(tex, buf.data(), GPU_TEXFACE_2D, 0);
|
||||
}
|
||||
|
||||
tex->border = 0x00000000;
|
||||
C3D_TexSetWrap(tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
|
||||
}
|
||||
void Texture::LoadFile(const std::string &path) {
|
||||
Palladium::Ftrace::ScopedTrace st("texldr", path);
|
||||
int w, h, c = 0;
|
||||
unsigned char *image = stbi_load(path.c_str(), &w, &h, &c, 4);
|
||||
if (image == nullptr) {
|
||||
//_pdi_logger()->Write("Failed to Load Image: " + path);
|
||||
return;
|
||||
}
|
||||
// Size/Fmt Check
|
||||
if (w > 1024 || h > 1024) {
|
||||
// Reason: Image to Large
|
||||
//_pdi_logger()->Write("Image too Large!");
|
||||
stbi_image_free(image);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> wimg;
|
||||
if (c == 3) {
|
||||
//_pdi_logger()->Write("Convert Image to RGBA");
|
||||
stbi_image_free(image);
|
||||
image = stbi_load(path.c_str(), &w, &h, &c, 3);
|
||||
wimg.resize(w * h * 4);
|
||||
pdi::RGB24toRGBA32(
|
||||
wimg, std::vector<unsigned char>(image, image + (w * h * 3)), w, h);
|
||||
} else {
|
||||
wimg.assign(&image[0], &image[(w * h * 4) - 1]);
|
||||
stbi_image_free(image);
|
||||
}
|
||||
// Create C2D_Image
|
||||
tex = new C3D_Tex;
|
||||
MakeTex(wimg, w, h);
|
||||
}
|
||||
|
||||
void Texture::LoadFromMemory(const std::vector<unsigned char> &data) {
|
||||
int w, h, c = 0;
|
||||
unsigned char *image =
|
||||
stbi_load_from_memory(data.data(), data.size(), &w, &h, &c, 4);
|
||||
if (image == nullptr) {
|
||||
//_pdi_logger()->Write("Failed to Load Image: " + path);
|
||||
return;
|
||||
}
|
||||
// Size/Fmt Check
|
||||
if (w > 1024 || h > 1024) {
|
||||
// Reason: Image to Large
|
||||
//_pdi_logger()->Write("Image too Large!");
|
||||
stbi_image_free(image);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> wimg;
|
||||
if (c == 3) {
|
||||
//_pdi_logger()->Write("Convert Image to RGBA");
|
||||
stbi_image_free(image);
|
||||
image = stbi_load_from_memory(data.data(), data.size(), &w, &h, &c, 3);
|
||||
wimg.resize(w * h * 4);
|
||||
pdi::RGB24toRGBA32(
|
||||
wimg, std::vector<unsigned char>(image, image + (w * h * 3)), w, h);
|
||||
} else {
|
||||
wimg.assign(&image[0], &image[(w * h * 4) - 1]);
|
||||
stbi_image_free(image);
|
||||
}
|
||||
// Create C2D_Image
|
||||
tex = new C3D_Tex;
|
||||
MakeTex(wimg, w, h);
|
||||
}
|
||||
|
||||
NVec2 Texture::GetTexSize() {
|
||||
if (!tex) return NVec2();
|
||||
return NVec2(tex->width, tex->height);
|
||||
}
|
||||
|
||||
void Texture::LoadPixels(const std::vector<unsigned char> &data, int w, int h,
|
||||
Type type, Filter filter) {
|
||||
Delete();
|
||||
int bpp = GetBPP(type);
|
||||
Palladium::InlineAssert(bpp, "Invalid Type");
|
||||
if (w * h * bpp != (int)data.size()) {
|
||||
return;
|
||||
}
|
||||
if (w > 1024 || h > 1024) {
|
||||
// Reason: Image to Large
|
||||
//_pdi_logger()->Write("Image too Large!");
|
||||
return;
|
||||
}
|
||||
tex = new C3D_Tex;
|
||||
std::vector<unsigned char> wimg(data);
|
||||
MakeTex(wimg, w, h, type, filter);
|
||||
}
|
||||
|
||||
void Texture::ExternalLoad(C3D_Tex *tex, NVec2 rszs, NVec4 uvs) {
|
||||
Delete();
|
||||
this->tex = tex;
|
||||
this->img_size = rszs;
|
||||
this->uvs = uvs;
|
||||
}
|
||||
|
||||
void Texture::Delete() {
|
||||
if (!ad) return;
|
||||
if (tex) {
|
||||
C3D_TexDelete(tex);
|
||||
delete tex;
|
||||
tex = nullptr;
|
||||
img_size = NVec2();
|
||||
this->uvs.x() = 0.0f;
|
||||
this->uvs.y() = 1.0f;
|
||||
this->uvs.z() = 1.0f;
|
||||
this->uvs.w() = 0.0f;
|
||||
}
|
||||
}
|
||||
} // namespace Palladium
|
@ -1,138 +0,0 @@
|
||||
#include <filesystem>
|
||||
#include <pd/Hid.hpp>
|
||||
#include <pd/Message.hpp>
|
||||
#include <pd/ThemeEditor.hpp>
|
||||
#include <pd/UI7.hpp>
|
||||
|
||||
std::map<PDColor, std::string> color_names = {
|
||||
{PDColor_Background, "Background"},
|
||||
{PDColor_Button, "Button"},
|
||||
{PDColor_ButtonActive, "ButtonActive"},
|
||||
{PDColor_ButtonDisabled, "ButtonDisabled"},
|
||||
{PDColor_ButtonHovered, "ButtonHovered"},
|
||||
{PDColor_Checkmark, "Checkmark"},
|
||||
{PDColor_FrameBg, "FrameBg"},
|
||||
{PDColor_FrameBgHovered, "FrameBgHovered"},
|
||||
{PDColor_Header, "Header"},
|
||||
{PDColor_List0, "List0"},
|
||||
{PDColor_List1, "List1"},
|
||||
{PDColor_MessageBackground, "Message Background"},
|
||||
{PDColor_Progressbar, "Progressbar"},
|
||||
{PDColor_Selector, "Selector"},
|
||||
{PDColor_SelectorFade, "SelectorFade"},
|
||||
{PDColor_Text2, "Text Light"},
|
||||
{PDColor_Text, "Text Dark"},
|
||||
{PDColor_TextDisabled, "Text Disabled"},
|
||||
};
|
||||
|
||||
Palladium::ThemeEditor::ThemeEditor() {
|
||||
// Backup active Theme and create New one to edit
|
||||
temp_theme = Palladium::ThemeActive();
|
||||
edit_theme = Palladium::Theme::New();
|
||||
edit_theme->CopyOther(temp_theme);
|
||||
Palladium::ThemeSet(edit_theme);
|
||||
}
|
||||
|
||||
Palladium::ThemeEditor::~ThemeEditor() {
|
||||
// Set Back to Acrive Theme
|
||||
Palladium::ThemeSet(temp_theme);
|
||||
}
|
||||
|
||||
void Palladium::ThemeEditor::Update() {
|
||||
// Rendering / UI Logic
|
||||
Palladium::LI::OnScreen(false);
|
||||
if (UI7::BeginMenu("Palladium -> Theme Editor")) {
|
||||
UI7::Label("Sample Text");
|
||||
UI7::Checkbox("Checkbox", cm);
|
||||
UI7::InputText("Input Text", inpt, "Input Text");
|
||||
UI7::Button("Button");
|
||||
UI7::Progressbar(0.5f);
|
||||
UI7::ColorSelector("Color Selector",
|
||||
edit_theme->GetTableRef()[PDColor_Progressbar]);
|
||||
UI7::EndMenu();
|
||||
}
|
||||
Palladium::LI::OnScreen(true);
|
||||
if (UI7::BeginMenu("Theme", NVec2(), UI7MenuFlags_Scrolling)) {
|
||||
if (menu == 0) {
|
||||
if (UI7::Button("Create New")) {
|
||||
menu = 1;
|
||||
edit_theme->Default();
|
||||
} else if (UI7::Button("Edit Current")) {
|
||||
menu = 1;
|
||||
} else if (UI7::Button("Select Theme")) {
|
||||
menu = 2;
|
||||
theme_list.clear();
|
||||
for (const auto& it : std::filesystem::directory_iterator(
|
||||
Palladium::GetAppDirectory() + "/themes")) {
|
||||
theme_list.push_back(it.path().filename().string());
|
||||
}
|
||||
}
|
||||
} else if (menu == 1) {
|
||||
if (UI7::Button("Go back")) {
|
||||
edit_theme->CopyOther(temp_theme);
|
||||
menu = 0;
|
||||
} else if (UI7::Button("Save")) {
|
||||
Palladium::AddOvl(std::make_unique<Ovl_Keyboard>(kbd_text, kbd_state,
|
||||
"<name>.theme"));
|
||||
}
|
||||
for (auto& it : color_names) {
|
||||
UI7::ColorSelector(it.second, edit_theme->GetTableRef()[it.first]);
|
||||
}
|
||||
} else if (menu == 2) {
|
||||
if (UI7::Button("Go back")) {
|
||||
menu = 0;
|
||||
}
|
||||
for (auto& it : theme_list) {
|
||||
if (UI7::Button(it)) {
|
||||
edit_theme->Load(Palladium::GetAppDirectory() + "/themes/" + it);
|
||||
menu = 1;
|
||||
}
|
||||
UI7::SameLine();
|
||||
if (UI7::Button("Make Current")) {
|
||||
edit_theme->Load(Palladium::GetAppDirectory() + "/themes/" + it);
|
||||
temp_theme->CopyOther(edit_theme);
|
||||
menu = 0;
|
||||
}
|
||||
UI7::SameLine();
|
||||
if (UI7::Button("Delete")) {
|
||||
if (std::string(it) != "Palladium.theme") {
|
||||
std::filesystem::remove(Palladium::GetAppDirectory() + "/themes/" +
|
||||
it);
|
||||
theme_list.clear();
|
||||
for (const auto& it : std::filesystem::directory_iterator(
|
||||
Palladium::GetAppDirectory() + "/themes")) {
|
||||
theme_list.push_back(it.path().filename().string());
|
||||
}
|
||||
} else {
|
||||
Palladium::PushMessage("ThemeEditor",
|
||||
"Cannot Delete\nPalladium.theme!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UI7::EndMenu();
|
||||
}
|
||||
|
||||
// Standart Logic
|
||||
if (kbd_state) {
|
||||
if (kbd_state == PDKeyboardState_Confirm) {
|
||||
auto path =
|
||||
Palladium::GetAppDirectory() + "/themes/" + kbd_text + ".theme";
|
||||
kbd_text = "";
|
||||
if (std::filesystem::exists(path)) {
|
||||
// Prompt Override
|
||||
return;
|
||||
}
|
||||
edit_theme->Save(path);
|
||||
}
|
||||
kbd_state = PDKeyboardState_None;
|
||||
}
|
||||
if (Hid::IsEvent("cancel", Hid::Down)) {
|
||||
if (menu == 0) {
|
||||
Palladium::Scene::Back();
|
||||
} else {
|
||||
if (menu == 1) edit_theme->CopyOther(temp_theme);
|
||||
menu = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <memory>
|
||||
#include <pd/Time.hpp>
|
||||
#include <string>
|
||||
|
||||
std::string Palladium::FormatString(std::string fmt_str, ...) {
|
||||
va_list ap;
|
||||
char *fp = NULL;
|
||||
va_start(ap, fmt_str);
|
||||
vasprintf(&fp, fmt_str.c_str(), ap);
|
||||
va_end(ap);
|
||||
std::unique_ptr<char, decltype(free) *> formatted(fp, free);
|
||||
return std::string(formatted.get());
|
||||
}
|
||||
|
||||
std::string Palladium::GetTimeStr(void) {
|
||||
time_t unixTime;
|
||||
struct tm timeStruct;
|
||||
time(&unixTime);
|
||||
localtime_r(&unixTime, &timeStruct);
|
||||
return FormatString("%04i-%02i-%02i_%02i-%02i-%02i",
|
||||
timeStruct.tm_year + 1900, timeStruct.tm_mon + 1,
|
||||
timeStruct.tm_mday, timeStruct.tm_hour, timeStruct.tm_min,
|
||||
timeStruct.tm_sec);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#include <pd/Timer.hpp>
|
||||
|
||||
// Ticks per MSEC
|
||||
#define TPMS 268111.856
|
||||
|
||||
namespace Palladium {
|
||||
Timer::Timer(bool autostart) {
|
||||
if (autostart) is_running = true;
|
||||
last = svcGetSystemTick();
|
||||
current = last;
|
||||
}
|
||||
|
||||
void Timer::Reset() {
|
||||
last = svcGetSystemTick();
|
||||
current = last;
|
||||
}
|
||||
|
||||
void Timer::Tick() {
|
||||
if (is_running) current = svcGetSystemTick();
|
||||
}
|
||||
|
||||
void Timer::Pause() { is_running = false; }
|
||||
|
||||
void Timer::Resume() { is_running = true; }
|
||||
|
||||
bool Timer::Running() { return is_running; }
|
||||
|
||||
float Timer::Get() { return (float)((current - last) / TPMS); }
|
||||
|
||||
float Timer::GetLive() { return (float)((svcGetSystemTick() - last) / TPMS); }
|
||||
} // namespace Palladium
|
1463
source/UI7.cpp
1463
source/UI7.cpp
File diff suppressed because it is too large
Load Diff
@ -1,229 +0,0 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <pd/base/Color.hpp>
|
||||
#include <pd/Message.hpp>
|
||||
#include <pd/external/json.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
|
||||
void pdi_swap32(unsigned int& c) {
|
||||
c = ((c & 0xFF) << 24) | ((c & 0xFF00) << 8) | ((c & 0xFF0000) >> 8) |
|
||||
((c & 0xFF000000) >> 24);
|
||||
}
|
||||
|
||||
std::string Palladium::Color::RGBA2Hex(unsigned int c32) {
|
||||
pdi_swap32(c32);
|
||||
std::stringstream ss;
|
||||
ss << "#";
|
||||
ss << std::hex << std::setw(8) << std::setfill('0') << c32;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Standart Color Converter
|
||||
static const std::map<char, int> HEX_TO_DEC = {
|
||||
{'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5},
|
||||
{'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'a', 10}, {'b', 11},
|
||||
{'c', 12}, {'d', 13}, {'e', 14}, {'f', 15}, {'A', 10}, {'B', 11},
|
||||
{'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}};
|
||||
|
||||
unsigned int pdi_special_color_hex(const std::string& hex) {
|
||||
if (hex.length() < 9 || std::find_if(hex.begin() + 1, hex.end(), [](char c) {
|
||||
return !std::isxdigit(c);
|
||||
}) != hex.end()) {
|
||||
return pdi_special_color_hex("#00000000");
|
||||
}
|
||||
|
||||
int r = HEX_TO_DEC.at(hex[1]) * 16 + HEX_TO_DEC.at(hex[2]);
|
||||
int g = HEX_TO_DEC.at(hex[3]) * 16 + HEX_TO_DEC.at(hex[4]);
|
||||
int b = HEX_TO_DEC.at(hex[5]) * 16 + HEX_TO_DEC.at(hex[6]);
|
||||
int a = HEX_TO_DEC.at(hex[7]) * 16 + HEX_TO_DEC.at(hex[8]);
|
||||
|
||||
return RGBA8(r, g, b, a);
|
||||
}
|
||||
|
||||
// Default Theme
|
||||
const std::map<PDColor, unsigned int> pdi_default_theme = {
|
||||
{PDColor_Text, RGBA8(0, 0, 0, 255)},
|
||||
{PDColor_Text2, RGBA8(255, 255, 255, 255)}, // For Background change or so
|
||||
{PDColor_TextDisabled, RGBA8(170, 170, 170, 255)},
|
||||
{PDColor_Background, RGBA8(238, 238, 238, 255)},
|
||||
{PDColor_Header, RGBA8(17, 17, 17, 255)},
|
||||
{PDColor_Selector, RGBA8(34, 34, 34, 255)},
|
||||
{PDColor_SelectorFade, RGBA8(90, 90, 90, 255)},
|
||||
{PDColor_List0, RGBA8(204, 204, 204, 255)}, // List0 = % 2
|
||||
{PDColor_List1, RGBA8(187, 187, 187, 255)},
|
||||
{PDColor_MessageBackground, RGBA8(51, 51, 51, 255)},
|
||||
{PDColor_Button, RGBA8(17, 17, 17, 255)},
|
||||
{PDColor_ButtonHovered, RGBA8(34, 34, 34, 255)},
|
||||
{PDColor_ButtonDisabled, RGBA8(8, 8, 8, 255)},
|
||||
{PDColor_ButtonActive, RGBA8(42, 42, 42, 255)},
|
||||
{PDColor_Checkmark, RGBA8(42, 42, 42, 255)},
|
||||
{PDColor_FrameBg, RGBA8(85, 85, 85, 255)},
|
||||
{PDColor_FrameBgHovered, RGBA8(119, 119, 119, 255)},
|
||||
{PDColor_Progressbar, RGBA8(0, 255, 0, 255)},
|
||||
};
|
||||
|
||||
void Palladium::Theme::Load(const std::string& path) {
|
||||
std::ifstream file(path);
|
||||
if (!file.is_open()) {
|
||||
return;
|
||||
}
|
||||
nlohmann::json js;
|
||||
file >> js;
|
||||
// clang-format off
|
||||
if(THEMEVER != js["version"]) {
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
this->clr_tab.clear();
|
||||
this->clr_tab.resize(PDColor_Len);
|
||||
this->clr_tab[PDColor_Text] = pdi_special_color_hex(js["PDColor_Text"].get<std::string>());
|
||||
this->clr_tab[PDColor_Text2] = pdi_special_color_hex(js["PDColor_Text2"].get<std::string>());
|
||||
this->clr_tab[PDColor_TextDisabled] = pdi_special_color_hex(js["PDColor_TextDisabled"].get<std::string>());
|
||||
this->clr_tab[PDColor_Background] = pdi_special_color_hex(js["PDColor_Background"].get<std::string>());
|
||||
this->clr_tab[PDColor_Header] = pdi_special_color_hex(js["PDColor_Header"].get<std::string>());
|
||||
this->clr_tab[PDColor_Selector] = pdi_special_color_hex(js["PDColor_Selector"].get<std::string>());
|
||||
this->clr_tab[PDColor_SelectorFade] = pdi_special_color_hex(js["PDColor_SelectorFade"].get<std::string>());
|
||||
this->clr_tab[PDColor_List0] = pdi_special_color_hex(js["PDColor_List0"].get<std::string>());
|
||||
this->clr_tab[PDColor_List1] = pdi_special_color_hex(js["PDColor_List1"].get<std::string>());
|
||||
this->clr_tab[PDColor_MessageBackground] = pdi_special_color_hex(js["PDColor_MessageBackground"].get<std::string>());
|
||||
this->clr_tab[PDColor_Button] = pdi_special_color_hex(js["PDColor_Button"].get<std::string>());
|
||||
this->clr_tab[PDColor_ButtonHovered] = pdi_special_color_hex(js["PDColor_ButtonHovered"].get<std::string>());
|
||||
this->clr_tab[PDColor_ButtonDisabled] = pdi_special_color_hex(js["PDColor_ButtonDisabled"].get<std::string>());
|
||||
this->clr_tab[PDColor_ButtonActive] = pdi_special_color_hex(js["PDColor_ButtonActive"].get<std::string>());
|
||||
this->clr_tab[PDColor_Checkmark] = pdi_special_color_hex(js["PDColor_Checkmark"].get<std::string>());
|
||||
this->clr_tab[PDColor_FrameBg] = pdi_special_color_hex(js["PDColor_FrameBg"].get<std::string>());
|
||||
this->clr_tab[PDColor_FrameBgHovered] = pdi_special_color_hex(js["PDColor_FrameBgHovered"].get<std::string>());
|
||||
this->clr_tab[PDColor_Progressbar] = pdi_special_color_hex(js["PDColor_Progressbar"].get<std::string>());
|
||||
// clang-format on
|
||||
file.close();
|
||||
}
|
||||
|
||||
void Palladium::Theme::Default() {
|
||||
this->clr_tab.clear();
|
||||
this->clr_tab.resize(PDColor_Len);
|
||||
for (auto& it : pdi_default_theme) {
|
||||
this->clr_tab[it.first] = it.second;
|
||||
}
|
||||
}
|
||||
|
||||
void Palladium::Theme::CopyOther(Theme::Ref theme) {
|
||||
this->clr_tab.clear();
|
||||
this->clr_tab.resize(PDColor_Len);
|
||||
for (int i = 0; i < (int)PDColor_Len; i++) {
|
||||
this->clr_tab[i] = theme->Get(i);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Palladium::Theme::Get(PDColor clr) {
|
||||
if (clr < 0 || clr >= PDColor_Len) return 0;
|
||||
return this->clr_tab[clr];
|
||||
}
|
||||
|
||||
void Palladium::Theme::Set(PDColor clr, unsigned int v) {
|
||||
if (clr < 0 || clr >= PDColor_Len) return;
|
||||
this->changes.push_back(change(clr, this->clr_tab[clr], v));
|
||||
this->clr_tab[clr] = v;
|
||||
}
|
||||
void Palladium::Theme::Swap(PDColor a, PDColor b) {
|
||||
if (a < 0 || a >= PDColor_Len || b < 0 || b >= PDColor_Len) return;
|
||||
auto c = this->clr_tab[a];
|
||||
this->clr_tab[a] = this->clr_tab[b];
|
||||
this->clr_tab[b] = c;
|
||||
this->changes.push_back(change(a, b, c, this->clr_tab[a]));
|
||||
}
|
||||
|
||||
void Palladium::Theme::TextBy(PDColor bg) {
|
||||
if (!Color::RGBA(bg).is_light()) Swap(PDColor_Text, PDColor_Text2);
|
||||
}
|
||||
|
||||
PDColor Palladium::Theme::AutoText(PDColor bg) {
|
||||
return Color::RGBA(bg).is_light() ? PDColor_Text : PDColor_Text2;
|
||||
}
|
||||
|
||||
bool Palladium::Theme::Undo() {
|
||||
if (!this->changes.size()) return false;
|
||||
auto ch = this->changes[this->changes.size() - 1];
|
||||
this->changes.pop_back();
|
||||
if (ch.clr2) {
|
||||
this->clr_tab[ch.clr2] = ch.to;
|
||||
this->clr_tab[ch.clr] = ch.from;
|
||||
} else {
|
||||
this->clr_tab[ch.clr] = ch.from;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Palladium::Theme::UndoAll() {
|
||||
while (Undo()) {
|
||||
// Just Run Undo Until all is undone
|
||||
}
|
||||
}
|
||||
|
||||
void Palladium::Theme::Save(const std::string& path) {
|
||||
if (std::filesystem::path(path).filename().string() == "Palladium.theme") {
|
||||
if (!pdi_amdt) {
|
||||
Palladium::PushMessage("Theme", "Default Theme cannot\nbe overwritten!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::ofstream file(path);
|
||||
if (!file.is_open()) {
|
||||
Palladium::PushMessage("Theme", "Unable to\ncreate file!");
|
||||
return;
|
||||
}
|
||||
nlohmann::json js;
|
||||
// clang-format off
|
||||
js["version"] = THEMEVER;
|
||||
js["PDColor_Text"] = Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_Text]);
|
||||
js["PDColor_Text2"] = Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_Text2]);
|
||||
js["PDColor_TextDisabled"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_TextDisabled]); js["PDColor_Background"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_Background]); js["PDColor_Header"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_Header]); js["PDColor_Selector"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_Selector]); js["PDColor_SelectorFade"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_SelectorFade]); js["PDColor_List0"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_List0]); js["PDColor_List1"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_List1]); js["PDColor_MessageBackground"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_MessageBackground]); js["PDColor_Button"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_Button]); js["PDColor_ButtonHovered"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_ButtonHovered]);
|
||||
js["PDColor_ButtonDisabled"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_ButtonDisabled]);
|
||||
js["PDColor_ButtonActive"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_ButtonActive]); js["PDColor_Checkmark"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_Checkmark]); js["PDColor_FrameBg"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_FrameBg]); js["PDColor_FrameBgHovered"] =
|
||||
Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_FrameBgHovered]); js["PDColor_Progressbar"]
|
||||
= Palladium::Color::RGBA2Hex(this->clr_tab[PDColor_Progressbar]);
|
||||
// clang-format on
|
||||
file << js.dump(4);
|
||||
file.close();
|
||||
}
|
||||
|
||||
Palladium::Theme::Ref Palladium::ThemeActive() { return pdi_active_theme; }
|
||||
|
||||
void Palladium::ThemeSet(Palladium::Theme::Ref theme) {
|
||||
pdi_active_theme = theme;
|
||||
}
|
||||
|
||||
unsigned int Palladium::Color::Hex(const std::string& color, uint8_t a) {
|
||||
if (color.length() < 7 ||
|
||||
std::find_if(color.begin() + 1, color.end(),
|
||||
[](char c) { return !std::isxdigit(c); }) != color.end()) {
|
||||
return Palladium::Color::Hex("#000000", 0);
|
||||
}
|
||||
|
||||
int r = HEX_TO_DEC.at(color[1]) * 16 + HEX_TO_DEC.at(color[2]);
|
||||
int g = HEX_TO_DEC.at(color[3]) * 16 + HEX_TO_DEC.at(color[4]);
|
||||
int b = HEX_TO_DEC.at(color[5]) * 16 + HEX_TO_DEC.at(color[6]);
|
||||
|
||||
return RGBA8(r, g, b, a);
|
||||
}
|
||||
|
||||
std::string Palladium::Color::RGB2Hex(int r, int g, int b) {
|
||||
std::stringstream ss;
|
||||
ss << "#";
|
||||
ss << std::hex << (r << 16 | g << 8 | b);
|
||||
return ss.str();
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
#include <3ds.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <pd/base/FileSystem.hpp>
|
||||
// Debugging
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <pd/base/stringtool.hpp>
|
||||
|
||||
bool ___dir__predicate__(const Palladium::FileSystem::Entry &lhs,
|
||||
const Palladium::FileSystem::Entry &rhs) {
|
||||
if (!lhs.dir && rhs.dir) return false;
|
||||
if (lhs.dir && !rhs.dir) return true;
|
||||
std::string a = lhs.name;
|
||||
std::string b = rhs.name;
|
||||
std::transform(a.begin(), a.end(), a.begin(),
|
||||
[](int i) { return std::tolower(i); });
|
||||
std::transform(b.begin(), b.end(), b.begin(),
|
||||
[](int i) { return std::tolower(i); });
|
||||
return a.compare(b) < 0;
|
||||
}
|
||||
|
||||
std::string Palladium::FileSystem::GetParentPath(std::string path,
|
||||
std::string mount_point) {
|
||||
std::string tcl = path;
|
||||
if (path.substr(path.length() - 1, 1) != "/") {
|
||||
tcl += "/";
|
||||
}
|
||||
std::string res =
|
||||
std::filesystem::path(tcl).parent_path().parent_path().string();
|
||||
if (res.length() > mount_point.length()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return mount_point;
|
||||
}
|
||||
|
||||
std::vector<Palladium::FileSystem::Entry> Palladium::FileSystem::GetDirContent(
|
||||
std::string path) {
|
||||
std::vector<Palladium::FileSystem::Entry> res;
|
||||
for (const auto &entry :
|
||||
std::filesystem::directory_iterator(std::filesystem::path(path))) {
|
||||
res.push_back({entry.path().string(), GetFileName(entry.path().string()),
|
||||
entry.is_directory()});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<Palladium::FileSystem::Entry>
|
||||
Palladium::FileSystem::GetDirContentsExt(
|
||||
std::string &path, const std::vector<std::string> &extensions) {
|
||||
std::vector<Palladium::FileSystem::Entry> res;
|
||||
for (auto const &it :
|
||||
std::filesystem::directory_iterator(std::filesystem::path(path))) {
|
||||
Palladium::FileSystem::Entry temp;
|
||||
std::string fn = it.path().string();
|
||||
temp.name = GetFileName(fn);
|
||||
temp.path = it.path().string().c_str();
|
||||
temp.dir = it.is_directory();
|
||||
if (NameIsEndingWith(GetFileName(it.path().string()), extensions) ||
|
||||
it.is_directory()) {
|
||||
res.push_back(temp);
|
||||
}
|
||||
}
|
||||
std::sort(res.begin(), res.end(), ___dir__predicate__);
|
||||
return res;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
#include <pd/base/FunctionTrace.hpp>
|
||||
|
||||
std::map<std::string, Palladium::Ftrace::FTRes> Palladium::Ftrace::pd_traces;
|
@ -1,125 +0,0 @@
|
||||
#include <3ds.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <pd/base/Lang.hpp>
|
||||
|
||||
static nlohmann::json appJson;
|
||||
|
||||
/// Lang Map KEY STRING
|
||||
static std::map<std::string, std::string> lang_table;
|
||||
|
||||
std::string Palladium::Lang::GetSys() {
|
||||
u8 language = 1;
|
||||
CFGU_GetSystemLanguage(&language);
|
||||
|
||||
switch (language) {
|
||||
case 0:
|
||||
return "jp"; // Japanese
|
||||
break;
|
||||
|
||||
case 1:
|
||||
return "en"; // English
|
||||
break;
|
||||
|
||||
case 2:
|
||||
return "fr"; // French
|
||||
break;
|
||||
|
||||
case 3:
|
||||
return "de"; // German
|
||||
break;
|
||||
|
||||
case 4:
|
||||
return "it"; // Italian
|
||||
break;
|
||||
|
||||
case 5:
|
||||
return "es"; // Spanish
|
||||
break;
|
||||
|
||||
case 6:
|
||||
return "zh-CN"; // Chinese (Simplified)
|
||||
break;
|
||||
|
||||
case 7:
|
||||
return "ko"; // Korean
|
||||
break;
|
||||
|
||||
case 8:
|
||||
return "nl"; // Dutch
|
||||
break;
|
||||
|
||||
case 9:
|
||||
return "pt"; // Portuguese
|
||||
break;
|
||||
|
||||
case 10:
|
||||
return "ru"; // Russian
|
||||
break;
|
||||
|
||||
case 11:
|
||||
return "zh-TW"; // Chinese (Traditional)
|
||||
break;
|
||||
|
||||
default:
|
||||
return "en"; // Fall back to English if missing
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string Palladium::Lang::Get(const std::string &key) {
|
||||
auto tmp = lang_table.find(key);
|
||||
if (tmp == lang_table.end()) return "ERR-02";
|
||||
return tmp->second;
|
||||
}
|
||||
|
||||
void Palladium::Lang::Load(const std::string &lang) {
|
||||
std::fstream values;
|
||||
if (std::filesystem::exists("romfs:/lang/" + lang + "/app.json")) {
|
||||
values.open("romfs:/lang/" + lang + "/app.json", std::ios::in);
|
||||
if (values.is_open()) {
|
||||
appJson = nlohmann::json::parse(values);
|
||||
}
|
||||
values.close();
|
||||
if (appJson.is_discarded()) {
|
||||
appJson = {};
|
||||
}
|
||||
} else {
|
||||
values.open("romfs:/lang/en/app.json", std::ios::in);
|
||||
if (values.is_open()) {
|
||||
appJson = nlohmann::json::parse(values);
|
||||
}
|
||||
values.close();
|
||||
if (appJson.is_discarded()) {
|
||||
appJson = {};
|
||||
}
|
||||
}
|
||||
lang_table.clear();
|
||||
if (appJson.contains("keys")) {
|
||||
for (auto &it : appJson["keys"].items()) {
|
||||
lang_table[it.key()] = it.value().get<std::string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Palladium::Lang::GetName() {
|
||||
if (!appJson.contains("info")) return "";
|
||||
nlohmann::json js = appJson["info"];
|
||||
if (!js.contains("name")) return "Unknown";
|
||||
return js.at("name").get<std::string>();
|
||||
}
|
||||
|
||||
std::string Palladium::Lang::GetAuthor() {
|
||||
if (!appJson.contains("info")) return "";
|
||||
nlohmann::json js = appJson["info"];
|
||||
if (!js.contains("author")) return "Unknown";
|
||||
return js.at("author").get<std::string>();
|
||||
}
|
||||
|
||||
std::string Palladium::Lang::GetShortcut() {
|
||||
if (!appJson.contains("info")) return "";
|
||||
nlohmann::json js = appJson["info"];
|
||||
if (!js.contains("shortcut")) return "Unknown";
|
||||
return js.at("shortcut").get<std::string>();
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <pd/base/Memory.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
|
||||
static Palladium::Memory::memory_metrics metrics;
|
||||
|
||||
void *operator new(size_t size) {
|
||||
void *ptr = malloc(size);
|
||||
if (pd_flags & PDFlags_MemTrack) metrics.t_TotalAllocated += size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void operator delete(void *memory, size_t size) {
|
||||
if (pd_flags & PDFlags_MemTrack) metrics.t_TotalFreed += size;
|
||||
free(memory);
|
||||
}
|
||||
|
||||
int allocations = 0;
|
||||
int total_size = 0;
|
||||
std::map<void *, size_t> sizes;
|
||||
|
||||
void *operator new[](size_t size) {
|
||||
void *ptr = malloc(size);
|
||||
if (pd_flags & PDFlags_MemTrack) {
|
||||
allocations++;
|
||||
total_size += size;
|
||||
sizes[ptr] = size;
|
||||
metrics.t_TotalAllocated += size;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void operator delete[](void *ptr) {
|
||||
if (pd_flags & PDFlags_MemTrack) {
|
||||
allocations--;
|
||||
total_size -= sizes[ptr];
|
||||
metrics.t_TotalFreed += sizes[ptr];
|
||||
sizes.erase(ptr);
|
||||
}
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
namespace Palladium {
|
||||
|
||||
namespace Memory {
|
||||
|
||||
size_t GetTotalAllocated() { return metrics.t_TotalAllocated; }
|
||||
|
||||
size_t GetTotalFreed() { return metrics.t_TotalFreed; }
|
||||
|
||||
size_t GetCurrent() { return metrics.t_CurrentlyAllocated(); }
|
||||
} // namespace Memory
|
||||
} // namespace Palladium
|
66
source/common/app.cpp
Normal file
66
source/common/app.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#include <pd/common/app.hpp>
|
||||
#include <pd/common/sys.hpp>
|
||||
|
||||
namespace PD {
|
||||
void App::Run() {
|
||||
this->PreInit();
|
||||
this->Init();
|
||||
last_time = Sys::GetTime();
|
||||
while (aptMainLoop()) {
|
||||
u64 current = Sys::GetTime();
|
||||
u64 dt = current - last_time;
|
||||
app_time += float(dt / 1000.f);
|
||||
last_time = current;
|
||||
fps = 1000.f / (float)dt;
|
||||
PD::TT::Beg("App_MainLoop");
|
||||
if (!this->MainLoop(dt, app_time)) {
|
||||
break;
|
||||
}
|
||||
PD::TT::End("App_MainLoop");
|
||||
renderer->Render();
|
||||
}
|
||||
this->Deinit();
|
||||
this->PostDeinit();
|
||||
}
|
||||
|
||||
void App::PreInit() {
|
||||
osSetSpeedupEnable(true);
|
||||
gfxInitDefault();
|
||||
cfguInit();
|
||||
romfsInit();
|
||||
renderer = LI::Renderer::New();
|
||||
}
|
||||
|
||||
void App::PostDeinit() {
|
||||
renderer = nullptr;
|
||||
gfxExit();
|
||||
cfguExit();
|
||||
romfsExit();
|
||||
}
|
||||
} // namespace PD
|
32
source/common/common.cpp
Normal file
32
source/common/common.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/common/common.hpp>
|
||||
|
||||
#ifndef PALLADIUM_VERSION
|
||||
#define PALLADIUM_VERSION "unknown"
|
||||
#endif
|
||||
#ifndef PALLADIUM_GIT_COMMIT
|
||||
#define PALLADIUM_GIT_COMMIT "unknown"
|
||||
#endif
|
50
source/common/error.cpp
Normal file
50
source/common/error.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#include <pd/common/error.hpp>
|
||||
|
||||
namespace PD {
|
||||
void Error(const std::string& msg) {
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_TOP, NULL);
|
||||
std::cout << "Palladium - ERROR MANAGER\n" << std::endl;
|
||||
std::cout << msg << std::endl << std::endl;
|
||||
std::cout << "Press Start to Exit" << std::endl;
|
||||
while (aptMainLoop()) {
|
||||
hidScanInput();
|
||||
if (hidKeysDown() & KEY_START) {
|
||||
break;
|
||||
}
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
gfxExit();
|
||||
exit(0);
|
||||
}
|
||||
void Assert(bool v, const std::string& msg) {
|
||||
if (v == false) {
|
||||
Error("Assert Failed:\n" + msg);
|
||||
}
|
||||
}
|
||||
} // namespace PD
|
61
source/common/lang.cpp
Normal file
61
source/common/lang.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/common/lang.hpp>
|
||||
#include <pd/external/json.hpp>
|
||||
|
||||
namespace PD {
|
||||
void Lang::LoadFile(const std::string &path) {
|
||||
nlohmann::json js;
|
||||
std::fstream iff(path, std::ios::in);
|
||||
if (iff.is_open()) {
|
||||
js = nlohmann::json::parse(iff);
|
||||
iff.close();
|
||||
if (js.is_discarded()) {
|
||||
return;
|
||||
}
|
||||
if (!js.contains("ver") || !js.contains("id") || !js.contains("name") ||
|
||||
!js.contains("author") || !js.contains("keys")) {
|
||||
return;
|
||||
}
|
||||
if (js["ver"].get<int>() != ver) {
|
||||
return;
|
||||
}
|
||||
lang_id = js["id"];
|
||||
lang_name = js["name"];
|
||||
lang_author = js["author"];
|
||||
ltable.clear();
|
||||
for (auto k : js["keys"].items()) {
|
||||
ltable.insert(std::make_pair(k.key(), k.value().get<std::string>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string &Lang::Get(const std::string &k) {
|
||||
auto e = ltable.find(k);
|
||||
if (e != ltable.end()) {
|
||||
return e->second;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
} // namespace PD
|
128
source/common/strings.cpp
Normal file
128
source/common/strings.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/common/strings.hpp>
|
||||
|
||||
namespace PD::Strings {
|
||||
bool StringEndsWith(const std::string& str,
|
||||
const std::vector<std::string>& exts) {
|
||||
// Changed order to not do an substr on empty string
|
||||
if (str.empty()) {
|
||||
return false;
|
||||
} else if (str.substr(0, 2) == "._") {
|
||||
return false;
|
||||
}
|
||||
// Use a more modern way here now
|
||||
// to avoid strcasecmp
|
||||
if (exts.size() != 0) {
|
||||
for (const auto& ext : exts) {
|
||||
if (str.substr(str.length() - ext.length()) == ext) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring MakeWstring(const std::string& s) {
|
||||
return std::wstring(s.begin(), s.end());
|
||||
}
|
||||
|
||||
const std::string FormatNanos(unsigned long long nanos) {
|
||||
// Based on some code of my minecraft plugins
|
||||
if (nanos < 1000) {
|
||||
return std::format("{}ns", nanos);
|
||||
} else if (nanos < 1000000) {
|
||||
unsigned long long micros = nanos / 1000;
|
||||
return std::format("{}us {}ns", micros, nanos % 1000);
|
||||
} else if (nanos < 1000000000) {
|
||||
unsigned long long millis = nanos / 1000000;
|
||||
return std::format("{}ms {}us", millis, (nanos % 1000000) / 1000);
|
||||
} else if (nanos < 60000000000ULL) {
|
||||
unsigned long long seconds = nanos / 1000000000;
|
||||
return std::format("{}s {}ms", seconds, (nanos % 1000000000) / 1000000);
|
||||
} else {
|
||||
unsigned long long minutes = nanos / 60000000000ULL;
|
||||
unsigned long long seconds = (nanos % 60000000000ULL) / 1000000000;
|
||||
return std::format("{}m {}s", minutes, seconds);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::string FormatMillis(unsigned long long millis) {
|
||||
// Original Code can be found in some of my mv plugins
|
||||
if (millis < 1000) {
|
||||
return std::format("{}ms", millis);
|
||||
} else if (millis < 60000) {
|
||||
unsigned long long seconds = millis / 1000;
|
||||
return std::format("{}s {}ms", seconds, (millis % 1000));
|
||||
} else {
|
||||
unsigned long long minutes = millis / 60000;
|
||||
unsigned long long seconds = (millis % 60000) / 1000;
|
||||
return std::format("{}m {}s {}ms", minutes, seconds, (millis % 1000));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::string FormatBytes(unsigned long long bytes) {
|
||||
static const std::vector<std::string> endings = {
|
||||
"B", "KB", "MB", "GB", "TB", "Unk",
|
||||
};
|
||||
int i = 0;
|
||||
double b = bytes;
|
||||
while (b > 1024.0) {
|
||||
i++;
|
||||
b /= 1024;
|
||||
}
|
||||
if (i >= (int)endings.size()) {
|
||||
i = (int)endings.size() - 1;
|
||||
}
|
||||
return std::format("{:.1f} {}", b, endings[i]);
|
||||
}
|
||||
|
||||
const std::string GetFileName(const std::string& path,
|
||||
const std::string& saperators) {
|
||||
auto pos = path.find_last_of(saperators);
|
||||
if (pos != path.npos) {
|
||||
return path.substr(pos + 1);
|
||||
}
|
||||
// If No saperator was found return the entire path
|
||||
return path;
|
||||
}
|
||||
|
||||
const std::string PathRemoveExtension(const std::string& path) {
|
||||
auto pos = path.find_last_of('.');
|
||||
if (pos != path.npos) {
|
||||
return path.substr(0, pos);
|
||||
}
|
||||
// If No saperator was found return the entire path
|
||||
return path;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const std::string ToHex(const T& v) {
|
||||
std::stringstream s;
|
||||
s << "0x" << std::setfill('0') << std::setw(sizeof(v) * 2) << std::hex << v;
|
||||
return s.str();
|
||||
}
|
||||
} // namespace PD::Strings
|
48
source/common/sys.cpp
Normal file
48
source/common/sys.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/common/sys.hpp>
|
||||
|
||||
namespace PD::Sys {
|
||||
TraceMap pd_sys_tm;
|
||||
u64 GetTime() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
u64 GetNanoTime() {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
TT::Res::Ref& GetTraceRef(const std::string& id) {
|
||||
// Auto Generate a New if doesnt exist
|
||||
if (pd_sys_tm.find(id) == pd_sys_tm.end()) {
|
||||
pd_sys_tm[id] = TT::Res::New();
|
||||
pd_sys_tm[id]->SetID(id);
|
||||
}
|
||||
return pd_sys_tm[id];
|
||||
}
|
||||
TraceMap& GetTraceMap() { return pd_sys_tm; }
|
||||
} // namespace PD::Sys
|
37
source/common/timetrace.cpp
Normal file
37
source/common/timetrace.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/common/sys.hpp>
|
||||
#include <pd/common/timetrace.hpp>
|
||||
|
||||
namespace PD::TT {
|
||||
void Beg(const std::string& id) {
|
||||
auto trace = Sys::GetTraceRef(id);
|
||||
trace->SetStart(PD::Sys::GetNanoTime());
|
||||
}
|
||||
|
||||
void End(const std::string& id) {
|
||||
auto trace = Sys::GetTraceRef(id);
|
||||
trace->SetEnd(PD::Sys::GetNanoTime());
|
||||
}
|
||||
} // namespace PD::TT
|
8
source/stb.cpp → source/external/stb.cpp
vendored
8
source/stb.cpp → source/external/stb.cpp
vendored
@ -1,6 +1,4 @@
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <pd/external/stb_image.h>
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <pd/external/stb_image_write.h>
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <pd/external/stb_image.h>
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include <pd/external/stb_truetype.h>
|
@ -1,6 +1,30 @@
|
||||
// THIS FILE WAS GENERATED BY build_shaders.py!!!
|
||||
|
||||
#include <pd/li7_shader.hpp>
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/graphics/li7_shader.hpp>
|
||||
|
||||
// clang-format off
|
||||
unsigned char li7_shader[] = {
|
662
source/graphics/lithium.cpp
Normal file
662
source/graphics/lithium.cpp
Normal file
@ -0,0 +1,662 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/external/stb_truetype.h>
|
||||
|
||||
#include <pd/common/strings.hpp>
|
||||
#include <pd/common/sys.hpp>
|
||||
#include <pd/graphics/li7_shader.hpp>
|
||||
#include <pd/graphics/lithium.hpp>
|
||||
#include <pd/maths/color.hpp>
|
||||
|
||||
namespace PD::LI {
|
||||
void Font::LoadTTF(const std::string& path, int height) {
|
||||
sysfont = false;
|
||||
TT::Scope st("LI_LoadTTF_" + path);
|
||||
pixel_height = height;
|
||||
int quad = height * 16;
|
||||
stbtt_fontinfo inf;
|
||||
std::ifstream loader(path, std::ios::binary);
|
||||
if (!loader.is_open()) return;
|
||||
loader.seekg(0, std::ios::end);
|
||||
size_t len = loader.tellg();
|
||||
loader.seekg(0, std::ios::beg);
|
||||
unsigned char* buffer = new unsigned char[len];
|
||||
loader.read(reinterpret_cast<char*>(buffer), len);
|
||||
loader.close();
|
||||
stbtt_InitFont(&inf, buffer, 0);
|
||||
std::vector<unsigned char> font_tex(quad * quad * 4);
|
||||
float scale = stbtt_ScaleForPixelHeight(&inf, pixel_height);
|
||||
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
|
||||
int baseline = static_cast<int>(ascent * scale);
|
||||
|
||||
auto tex = Texture::New();
|
||||
vec2 off;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
Codepoint c;
|
||||
if (stbtt_IsGlyphEmpty(&inf, i)) {
|
||||
c.cp(i);
|
||||
c.tex(tex);
|
||||
c.invalid(true);
|
||||
cpmap[i] = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
int w = 0, h = 0, xo = 0, yo = 0;
|
||||
unsigned char* bitmap =
|
||||
stbtt_GetCodepointBitmap(&inf, scale, scale, i, &w, &h, &xo, &yo);
|
||||
int x0, y0, x1, y1;
|
||||
stbtt_GetCodepointBitmapBox(&inf, i, scale, scale, &x0, &y0, &x1, &y1);
|
||||
|
||||
if (off[0] + w > quad) {
|
||||
off[1] += pixel_height;
|
||||
off[0] = 0;
|
||||
}
|
||||
|
||||
c.uv(vec4(static_cast<float>(off.x() / (float)quad),
|
||||
static_cast<float>(1.f - (off.y() / (float)quad)),
|
||||
static_cast<float>((float)(off.x() + w) / (float)quad),
|
||||
static_cast<float>((float)(off.y() + h) / (float)quad)));
|
||||
|
||||
c.tex(tex);
|
||||
c.size(vec2(w, h));
|
||||
c.off(baseline + yo);
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
int map_pos = ((off[1] + y) * quad + (off[0] + x)) * 4;
|
||||
|
||||
font_tex[map_pos + 0] = 255;
|
||||
font_tex[map_pos + 1] = 255;
|
||||
font_tex[map_pos + 2] = 255;
|
||||
font_tex[map_pos + 3] = bitmap[x + y * w];
|
||||
}
|
||||
}
|
||||
off[0] += w;
|
||||
if (off[0] + w > quad) {
|
||||
off[1] += pixel_height;
|
||||
off[0] = 0;
|
||||
}
|
||||
free(bitmap);
|
||||
cpmap[i] = c;
|
||||
}
|
||||
tex->LoadPixels(font_tex, quad, quad, Texture::RGBA32, Texture::LINEAR);
|
||||
textures.push_back(tex);
|
||||
}
|
||||
|
||||
Font::Codepoint& Font::GetCodepoint(u32 cp) {
|
||||
auto res = cpmap.find(cp);
|
||||
if (res == cpmap.end()) {
|
||||
static Codepoint invalid;
|
||||
return invalid.invalid(true);
|
||||
}
|
||||
return res->second;
|
||||
}
|
||||
|
||||
void Font::LoadSystemFont() {
|
||||
TT::Scope st("LI_SystemFont");
|
||||
sysfont = true;
|
||||
fontEnsureMapped();
|
||||
const auto fnt = fontGetSystemFont();
|
||||
const auto fnt_info = fontGetInfo(fnt);
|
||||
const auto glyph_info = fontGetGlyphInfo(fnt);
|
||||
this->textures.resize(glyph_info->nSheets + 1);
|
||||
pixel_height = glyph_info->cellHeight;
|
||||
for (size_t i = 0; i < glyph_info->nSheets; i++) {
|
||||
auto stex = Texture::New();
|
||||
auto tx = new C3D_Tex;
|
||||
tx->data = fontGetGlyphSheetTex(fnt, i);
|
||||
tx->fmt = (GPU_TEXCOLOR)glyph_info->sheetFmt;
|
||||
tx->size = glyph_info->sheetSize;
|
||||
tx->width = glyph_info->sheetWidth;
|
||||
tx->height = glyph_info->sheetHeight;
|
||||
tx->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) |
|
||||
GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
|
||||
GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT);
|
||||
tx->border = 0xffffffff;
|
||||
tx->lodParam = 0;
|
||||
stex->LoadExternal(tx, vec2(tx->width, tx->height), vec4(0, 1, 1, 0));
|
||||
textures[i] = stex;
|
||||
}
|
||||
std::vector<unsigned int> charSet;
|
||||
for (auto cmap = fnt_info->cmap; cmap; cmap = cmap->next) {
|
||||
if (cmap->mappingMethod == CMAP_TYPE_DIRECT) {
|
||||
if (cmap->codeEnd >= cmap->codeBegin) {
|
||||
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
|
||||
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
|
||||
if (cmap->indexOffset + (i - cmap->codeBegin) == 0xFFFF) break;
|
||||
charSet.emplace_back(i);
|
||||
}
|
||||
}
|
||||
} else if (cmap->mappingMethod == CMAP_TYPE_TABLE) {
|
||||
if (cmap->codeEnd >= cmap->codeBegin) {
|
||||
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
|
||||
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
|
||||
if (cmap->indexTable[i - cmap->codeBegin] == 0xFFFF) continue;
|
||||
charSet.emplace_back(i);
|
||||
}
|
||||
}
|
||||
} else if (cmap->mappingMethod == CMAP_TYPE_SCAN) {
|
||||
charSet.reserve(charSet.size() + cmap->nScanEntries);
|
||||
for (unsigned i = 0; i < cmap->nScanEntries; ++i) {
|
||||
if (cmap->scanEntries[i].code >= cmap->codeBegin &&
|
||||
cmap->scanEntries[i].code <= cmap->codeEnd) {
|
||||
if (cmap->scanEntries[i].glyphIndex != 0xFFFF) {
|
||||
charSet.emplace_back(cmap->scanEntries[i].code);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(charSet.begin(), charSet.end());
|
||||
charSet.erase(std::unique(charSet.begin(), charSet.end()));
|
||||
|
||||
for (auto cp : charSet) {
|
||||
int gidx = fontGlyphIndexFromCodePoint(fnt, cp);
|
||||
if (gidx >= 0xFFFF) continue;
|
||||
Codepoint codepoint;
|
||||
fontGlyphPos_s dat;
|
||||
fontCalcGlyphPos(&dat, fnt, gidx, GLYPH_POS_CALC_VTXCOORD, 1.f, 1.f);
|
||||
|
||||
codepoint.cp(cp);
|
||||
codepoint.uv(vec4(dat.texcoord.left, dat.texcoord.top, dat.texcoord.right,
|
||||
dat.texcoord.bottom));
|
||||
|
||||
if (textures.at(dat.sheetIndex) != nullptr) {
|
||||
codepoint.tex(textures[dat.sheetIndex]);
|
||||
}
|
||||
codepoint.size(vec2(dat.vtxcoord.right, dat.vtxcoord.bottom));
|
||||
codepoint.off(0);
|
||||
cpmap[cp] = codepoint;
|
||||
}
|
||||
}
|
||||
|
||||
Renderer::Renderer(RenderFlags flags) {
|
||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
top = Screen::New(Screen::Top);
|
||||
bot = Screen::New(Screen::Bottom);
|
||||
top->Clear();
|
||||
bot->Clear();
|
||||
|
||||
vertex_buf.resize(4 * 4096, Vertex());
|
||||
index_buf.resize(6 * 4096, 0);
|
||||
|
||||
/// Use 3ds u32 here
|
||||
dvlb = DVLB_ParseFile((uint32_t*)li7_shader, li7_shader_size);
|
||||
shaderProgramInit(&shader);
|
||||
shaderProgramSetVsh(&shader, &dvlb->DVLE[0]);
|
||||
uLoc_projection =
|
||||
shaderInstanceGetUniformLocation(shader.vertexShader, "projection");
|
||||
|
||||
AttrInfo_Init(&attr);
|
||||
AttrInfo_AddLoader(&attr, 0, GPU_FLOAT, 3);
|
||||
AttrInfo_AddLoader(&attr, 1, GPU_FLOAT, 2);
|
||||
AttrInfo_AddLoader(&attr, 2, GPU_UNSIGNED_BYTE, 4);
|
||||
|
||||
// Precalculate Projection (Never changes)
|
||||
Mtx_OrthoTilt(&top_proj, 0.f, 400.f, 240.f, 0.f, 1.f, -1.f, false);
|
||||
Mtx_OrthoTilt(&bot_proj, 0.f, 320.f, 240.f, 0.f, 1.f, -1.f, false);
|
||||
|
||||
std::vector<u8> pixels(16 * 16 * 4, 255);
|
||||
white = Texture::New(pixels, 16, 16);
|
||||
UseTex(white);
|
||||
|
||||
font = Font::New();
|
||||
font->LoadSystemFont();
|
||||
// font->LoadTTF("romfs:/ComicNeue.ttf", 32);
|
||||
|
||||
area_size = top->GetSize();
|
||||
}
|
||||
Renderer::~Renderer() {
|
||||
shaderProgramFree(&shader);
|
||||
DVLB_Free(dvlb);
|
||||
C3D_Fini();
|
||||
}
|
||||
|
||||
bool Renderer::InBox(vec2 pos, vec2 szs, vec4 rect) {
|
||||
return (pos[0] < rect[2] || pos[1] < rect[3] || pos[0] + szs[0] > rect[0] ||
|
||||
pos[1] + szs[1] > rect[1]);
|
||||
}
|
||||
|
||||
bool Renderer::InBox(vec2 alpha, vec2 bravo, vec2 charlie, vec4 rect) {
|
||||
return ((alpha[0] < rect[2] && bravo[0] < rect[2] && charlie[0] < rect[2]) ||
|
||||
(alpha[1] < rect[3] && bravo[1] < rect[3] && charlie[1] < rect[3]) ||
|
||||
(alpha[0] > 0 && bravo[0] > 0 && charlie[0] > 0) ||
|
||||
(alpha[1] > 0 && bravo[1] > 0 && charlie[1] > 0));
|
||||
}
|
||||
|
||||
void Renderer::RotateCorner(vec2& v, float s, float c) {
|
||||
float x = v[0] * c - v[1] * s;
|
||||
float y = v[1] * c + v[0] * s;
|
||||
v = vec2(x, y);
|
||||
}
|
||||
|
||||
Rect Renderer::CreateRect(vec2 pos, vec2 size, float angle) {
|
||||
vec2 c = size * 0.5f; // Center
|
||||
vec2 corner[4] = {
|
||||
vec2(-c[0], -c[1]),
|
||||
vec2(-c[0] + size[0], -c[1]),
|
||||
vec2(-c[0], -c[1] + size[1]),
|
||||
vec2(-c[0] + size[0], -c[1] + size[1]),
|
||||
};
|
||||
|
||||
// Only rotate if required
|
||||
if (angle != 0.f) {
|
||||
float s = std::sin(angle);
|
||||
float co = std::cos(angle);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
RotateCorner(corner[i], s, co);
|
||||
}
|
||||
}
|
||||
|
||||
// Return Result
|
||||
return Rect(corner[0] + pos + c, corner[1] + pos + c, corner[2] + pos + c,
|
||||
corner[3] + pos + c);
|
||||
}
|
||||
|
||||
Rect Renderer::CreateLine(vec2 a, vec2 b, int t) {
|
||||
// Usin g th evec maths api makes the code as short as it is
|
||||
vec2 dir = a - b;
|
||||
float len = dir.len();
|
||||
vec2 unit_dir = dir / len;
|
||||
vec2 perpendicular(-unit_dir.y(), unit_dir.x());
|
||||
vec2 off = perpendicular * ((float)t * 0.5f);
|
||||
|
||||
return Rect(a + off, b + off, a - off, b - off);
|
||||
}
|
||||
|
||||
void Renderer::OptiCommandList(std::vector<Command::Ref>& list) {
|
||||
std::sort(list.begin(), list.end(), [](Command::Ref a, Command::Ref b) {
|
||||
if (a->Layer() == b->Layer()) {
|
||||
if (a->Tex() == b->Tex()) {
|
||||
return a->Index() < b->Index();
|
||||
}
|
||||
return a->Tex() < b->Tex(); // else
|
||||
}
|
||||
return a->Layer() < b->Layer(); // else
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::SetupCommand(Command::Ref cmd) {
|
||||
cmd->Index(cmd_idx++).Layer(current_layer).Tex(current_tex);
|
||||
}
|
||||
|
||||
void Renderer::QuadCommand(Command::Ref cmd, const Rect& quad, vec4 uv,
|
||||
u32 col) {
|
||||
cmd->PushIndex(0).PushIndex(1).PushIndex(2);
|
||||
cmd->PushIndex(0).PushIndex(2).PushIndex(3);
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Bot().z(), quad.Bot().w()), vec2(uv.z(), uv.w()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Top().z(), quad.Top().w()), vec2(uv.z(), uv.y()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Top().x(), quad.Top().y()), vec2(uv.x(), uv.y()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Bot().x(), quad.Bot().y()), vec2(uv.x(), uv.w()), col));
|
||||
}
|
||||
|
||||
void Renderer::TriangleCommand(Command::Ref cmd, vec2 a, vec2 b, vec2 c,
|
||||
u32 col) {
|
||||
cmd->Index(cmd_idx++).Layer(current_layer).Tex(current_tex);
|
||||
cmd->PushIndex(2).PushIndex(1).PushIndex(0);
|
||||
cmd->PushVertex(Vertex(a, vec2(0.f, 1.f), col));
|
||||
cmd->PushVertex(Vertex(b, vec2(1.f, 1.f), col));
|
||||
cmd->PushVertex(Vertex(c, vec2(1.f, 0.f), col));
|
||||
}
|
||||
|
||||
/// TO BE REWRITTEN
|
||||
void Renderer::TextCommand(std::vector<Command::Ref>& cmds, vec2 pos, u32 color,
|
||||
const std::string& text, LITextFlags flags,
|
||||
vec2 box) {
|
||||
if (!font) {
|
||||
return;
|
||||
}
|
||||
vec2 off;
|
||||
float cfs = (default_font_h * text_size) / (float)font->PixelHeight();
|
||||
float lh = (float)font->PixelHeight() * cfs;
|
||||
vec2 td;
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream iss(text);
|
||||
std::string tmp;
|
||||
while (std::getline(iss, tmp)) {
|
||||
lines.push_back(tmp);
|
||||
}
|
||||
|
||||
for (auto& it : lines) {
|
||||
if (pos[1] + off[1] + lh < 0) {
|
||||
off[1] += lh;
|
||||
continue;
|
||||
} else if (pos[1] + off[1] > GetViewport().w()) {
|
||||
// Break cause next lines would be out of screen
|
||||
break;
|
||||
}
|
||||
auto wline = Strings::MakeWstring(it);
|
||||
auto cmd = Command::New();
|
||||
current_tex = font->GetCodepoint(wline[0]).tex();
|
||||
SetupCommand(cmd);
|
||||
if (font->SystemFont()) {
|
||||
cmd->Rendermode(RenderMode_SysFont);
|
||||
}
|
||||
for (auto& jt : wline) {
|
||||
auto cp = font->GetCodepoint(jt);
|
||||
if (cp.invalid() && jt != '\n' && jt != '\t') {
|
||||
continue;
|
||||
}
|
||||
if (current_tex != cp.tex()) {
|
||||
cmds.push_back(cmd);
|
||||
cmd = Command::New();
|
||||
current_tex = cp.tex();
|
||||
SetupCommand(cmd);
|
||||
if (font->SystemFont()) {
|
||||
cmd->Rendermode(RenderMode_SysFont);
|
||||
}
|
||||
}
|
||||
if (jt == '\t') {
|
||||
off[0] += 4 * cfs;
|
||||
} else {
|
||||
if (jt != ' ') {
|
||||
int lr = current_layer;
|
||||
if (flags & LITextFlags_Shaddow) {
|
||||
// Draw
|
||||
Rect rec = CreateRect(
|
||||
pos + vec2(off[0] + 1, off[1] + (cp.off() * cfs)) + 1,
|
||||
cp.size() * cfs, 0.f);
|
||||
QuadCommand(cmd, rec, cp.uv(), 0xff111111);
|
||||
current_layer++;
|
||||
}
|
||||
// Draw
|
||||
Rect rec = CreateRect(pos + off + vec2(0, (cp.off() * cfs)),
|
||||
cp.size() * cfs, 0.f);
|
||||
QuadCommand(cmd, rec, cp.uv(), color);
|
||||
current_layer = lr;
|
||||
}
|
||||
off[0] += cp.size().x() * cfs + 2 * cfs;
|
||||
}
|
||||
}
|
||||
cmds.push_back(cmd);
|
||||
off[1] += lh;
|
||||
off[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 Renderer::GetViewport() {
|
||||
auto screen = bottom ? bot->GetSize() : top->GetSize();
|
||||
return vec4(0, 0, screen[0], screen[1]);
|
||||
}
|
||||
|
||||
/// TO BE REWRITTEN
|
||||
vec2 Renderer::GetTextDimensions(const std::string& text) {
|
||||
if (!font) {
|
||||
// No font no size (oder so)
|
||||
return vec2();
|
||||
}
|
||||
// Handle TextMapSystem
|
||||
if (flags & RenderFlags_TMS) {
|
||||
auto ref = tms.find(text);
|
||||
if (ref != tms.end()) {
|
||||
ref->second.TimeCreated(Sys::GetTime());
|
||||
return ref->second.Size();
|
||||
}
|
||||
}
|
||||
// Use wstring for exemple for german äöü
|
||||
auto wtext = Strings::MakeWstring(text);
|
||||
// Create a temp position and offset as [0, 0]
|
||||
vec2 res;
|
||||
float x = 0;
|
||||
// Curent Font Scale
|
||||
float cfs = (default_font_h * text_size) / (float)font->PixelHeight();
|
||||
float lh = (float)font->PixelHeight() * cfs;
|
||||
size_t index = 0;
|
||||
for (auto& it : wtext) {
|
||||
if (it == '\0') {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
auto cp = font->GetCodepoint(it);
|
||||
if (cp.invalid() && it != '\n' && it != '\t' && it != ' ') {
|
||||
continue;
|
||||
}
|
||||
switch (it) {
|
||||
case '\n':
|
||||
res[1] += lh;
|
||||
res[0] = std::max(res[0], x);
|
||||
x = 0.f;
|
||||
break;
|
||||
case '\t':
|
||||
x += 8 * cfs;
|
||||
break;
|
||||
default:
|
||||
x += cp.size().x() * cfs;
|
||||
if (index != wtext.size()) {
|
||||
x += 2 * cfs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
res[0] = std::max(res[0], x);
|
||||
res[1] += lh;
|
||||
if (flags & RenderFlags_TMS) {
|
||||
tms[text] = TextBox(res, Sys::GetTime());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void Renderer::UpdateRenderMode(const RenderMode& mode) {
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
switch (mode) {
|
||||
case RenderMode_SysFont:
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0,
|
||||
(GPU_TEVSRC)0);
|
||||
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
|
||||
C3D_TexEnvSrc(env, C3D_Alpha, GPU_PRIMARY_COLOR, GPU_TEXTURE0,
|
||||
(GPU_TEVSRC)0);
|
||||
C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
|
||||
break;
|
||||
// Fall trough instead of defining twice
|
||||
case RenderMode_RGBA:
|
||||
default:
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR,
|
||||
(GPU_TEVSRC)0);
|
||||
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::RenderOn(bool bot) {
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection,
|
||||
(bot ? &bot_proj : &top_proj));
|
||||
|
||||
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
|
||||
|
||||
UpdateRenderMode(RenderMode_RGBA);
|
||||
|
||||
int total_vertices = 0;
|
||||
int total_indices = 0;
|
||||
drawcalls = 0;
|
||||
auto& cmds = draw_list[bot];
|
||||
|
||||
commands = cmds.size();
|
||||
size_t index = 0;
|
||||
|
||||
if (flags & RenderFlags_LRS) {
|
||||
OptiCommandList(cmds);
|
||||
}
|
||||
|
||||
while (index < cmds.size()) {
|
||||
C3D_Tex* tex = cmds[index]->Tex()->GetTex();
|
||||
auto mode = cmds[index]->Rendermode();
|
||||
UpdateRenderMode(mode);
|
||||
u32 start_vtx = vertex_idx;
|
||||
u32 start_idx = index_idx;
|
||||
while (index < cmds.size() && cmds[index]->Tex()->GetTex() == tex &&
|
||||
cmds[index]->Rendermode() == mode) {
|
||||
auto c = cmds[index];
|
||||
// Indices
|
||||
for (size_t i = 0; i < c->IndexList().size(); i++) {
|
||||
index_buf[index_idx++] = vertex_idx + c->IndexList().at(i);
|
||||
}
|
||||
// Vertices
|
||||
for (size_t i = 0; i < c->VertexList().size(); i++) {
|
||||
vertex_buf[vertex_idx++] = c->VertexList().at(i);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
C3D_TexBind(0, tex);
|
||||
|
||||
auto bufInfo = C3D_GetBufInfo();
|
||||
BufInfo_Init(bufInfo);
|
||||
BufInfo_Add(bufInfo, vertex_buf.data(), sizeof(Vertex), 3, 0x210);
|
||||
|
||||
C3D_DrawElements(GPU_TRIANGLES, index_idx - start_idx, C3D_UNSIGNED_SHORT,
|
||||
index_buf.data() + start_idx);
|
||||
drawcalls++;
|
||||
total_vertices += vertex_idx - start_vtx;
|
||||
total_indices += index_idx - start_idx;
|
||||
}
|
||||
cmds.clear();
|
||||
C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL);
|
||||
vertices = total_vertices;
|
||||
indices = total_indices;
|
||||
}
|
||||
|
||||
void Renderer::Render() {
|
||||
if (font_update) {
|
||||
tms.clear();
|
||||
font_update = false;
|
||||
}
|
||||
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
||||
TT::Beg("LI_RenderAll");
|
||||
top->Clear();
|
||||
bot->Clear();
|
||||
vertex_idx = 0;
|
||||
index_idx = 0;
|
||||
C3D_BindProgram(&shader);
|
||||
C3D_SetAttrInfo(&attr);
|
||||
top->Use();
|
||||
RenderOn(false);
|
||||
int dtc = commands;
|
||||
int dtd = drawcalls;
|
||||
int dtv = vertices;
|
||||
int dti = indices;
|
||||
bot->Use();
|
||||
RenderOn(true);
|
||||
TT::End("LI_RenderAll");
|
||||
C3D_FrameEnd(0);
|
||||
commands += dtc;
|
||||
drawcalls += dtd;
|
||||
vertices += dtv;
|
||||
indices += dti;
|
||||
current_layer = 0;
|
||||
cmd_idx = 0;
|
||||
area_size = top->GetSize();
|
||||
bottom = false;
|
||||
rot = 0.f;
|
||||
UseTex();
|
||||
if (flags & RenderFlags_TMS) {
|
||||
std::vector<std::string> rem;
|
||||
for (auto& it : tms) {
|
||||
if (Sys::GetTime() - it.second.TimeCreated() > 5) rem.push_back(it.first);
|
||||
}
|
||||
for (auto it : rem) tms.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::DrawRect(vec2 pos, vec2 size, u32 color, vec4 uv) {
|
||||
if (!InBox(pos, size, GetViewport())) {
|
||||
// Instand abort as it is out of screen
|
||||
return;
|
||||
}
|
||||
Rect rec = CreateRect(pos, size, rot);
|
||||
auto cmd = Command::New();
|
||||
SetupCommand(cmd);
|
||||
QuadCommand(cmd, rec, uv, color);
|
||||
draw_list[bottom].push_back(cmd);
|
||||
}
|
||||
|
||||
void Renderer::DrawRectSolid(vec2 pos, vec2 size, u32 color) {
|
||||
UseTex();
|
||||
DrawRect(pos, size, color);
|
||||
}
|
||||
|
||||
void Renderer::DrawTriangle(vec2 a, vec2 b, vec2 c, u32 color) {
|
||||
if (!InBox(a, b, c, GetViewport())) {
|
||||
return;
|
||||
}
|
||||
UseTex();
|
||||
auto cmd = Command::New();
|
||||
SetupCommand(cmd);
|
||||
TriangleCommand(cmd, a, b, c, color);
|
||||
draw_list[bottom].push_back(cmd);
|
||||
}
|
||||
|
||||
void Renderer::DrawCircle(vec2 center_pos, float r, u32 color, int segments) {
|
||||
if (segments < 3) {
|
||||
return;
|
||||
}
|
||||
auto cmd = Command::New();
|
||||
cmd->Index(cmd_idx++).Layer(current_layer).Tex(current_tex);
|
||||
for (int i = 1; i < segments - 1; i++) {
|
||||
cmd->PushIndex(0);
|
||||
cmd->PushIndex(i + 1).PushIndex(i);
|
||||
}
|
||||
float as = 2.f * M_PI / segments;
|
||||
for (int i = 0; i < segments; i++) {
|
||||
float a = i * as;
|
||||
float x = center_pos.x() + r * std::cos(a);
|
||||
float y = center_pos.y() + r * std::sin(a);
|
||||
cmd->PushVertex(Vertex(
|
||||
vec2(x, y), vec2((std::cos(a) + 1.f) / 2.f, (std::sin(a) + 1.f) / 2.f),
|
||||
color));
|
||||
}
|
||||
draw_list[bottom].push_back(cmd);
|
||||
}
|
||||
|
||||
void Renderer::DrawLine(vec2 a, vec2 b, u32 color, int t) {
|
||||
UseTex();
|
||||
Rect line = CreateLine(a, b, t);
|
||||
|
||||
auto cmd = Command::New();
|
||||
SetupCommand(cmd);
|
||||
QuadCommand(cmd, line, vec4(0.f, 1.f, 1.f, 0.f), color);
|
||||
draw_list[bottom].push_back(cmd);
|
||||
}
|
||||
|
||||
void Renderer::DrawImage(vec2 pos, Texture::Ref tex, vec2 scale) {
|
||||
UseTex(tex);
|
||||
DrawRect(pos, tex->GetSize() * scale, 0xffffffff, tex->GetUV());
|
||||
}
|
||||
|
||||
void Renderer::DrawText(vec2 pos, u32 color, const std::string& text, u32 flags,
|
||||
vec2 ap) {
|
||||
TextCommand(draw_list[bottom], pos, color, text, flags, ap);
|
||||
}
|
||||
|
||||
} // namespace PD::LI
|
203
source/graphics/texture.cpp
Normal file
203
source/graphics/texture.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
#include <pd/external/stb_image.h>
|
||||
|
||||
#include <pd/common/timetrace.hpp>
|
||||
#include <pd/graphics/texture.hpp>
|
||||
#include <pd/maths/bit_util.hpp>
|
||||
#include <pd/maths/img_convert.hpp>
|
||||
#include <pd/common/error.hpp>
|
||||
|
||||
namespace PD {
|
||||
GPU_TEXCOLOR GetTexFmt(Texture::Type type) {
|
||||
if (type == Texture::RGBA32)
|
||||
return GPU_RGBA8;
|
||||
else if (type == Texture::RGB24)
|
||||
return GPU_RGB8;
|
||||
else if (type == Texture::A8)
|
||||
return GPU_A8;
|
||||
return GPU_RGBA8; // Default
|
||||
}
|
||||
int GetBPP(Texture::Type type) {
|
||||
if (type == Texture::RGBA32)
|
||||
return 4;
|
||||
else if (type == Texture::RGB24)
|
||||
return 3;
|
||||
else if (type == Texture::A8)
|
||||
return 1;
|
||||
return 0; // Error
|
||||
}
|
||||
void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
Filter filter) {
|
||||
// Don't check here as check done before
|
||||
int bpp = GetBPP(type);
|
||||
if (bpp == 4) {
|
||||
// RGBA -> Abgr
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int pos = (x + y * w) * bpp;
|
||||
auto r = buf[pos + 0];
|
||||
auto g = buf[pos + 1];
|
||||
auto b = buf[pos + 2];
|
||||
auto a = buf[pos + 3];
|
||||
buf[pos + 0] = a;
|
||||
buf[pos + 1] = b;
|
||||
buf[pos + 2] = g;
|
||||
buf[pos + 3] = r;
|
||||
}
|
||||
}
|
||||
} else if (bpp == 3) {
|
||||
// RGBA -> Abgr
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int pos = (x + y * w) * bpp;
|
||||
auto r = buf[pos + 0];
|
||||
auto g = buf[pos + 1];
|
||||
auto b = buf[pos + 2];
|
||||
buf[pos + 0] = b;
|
||||
buf[pos + 1] = g;
|
||||
buf[pos + 2] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec2 tex_size(w, h);
|
||||
// Pow2
|
||||
if (!PD::BitUtil::IsSingleBit(w)) {
|
||||
tex_size.x() = PD::BitUtil::GetPow2((unsigned int)w);
|
||||
}
|
||||
if (!PD::BitUtil::IsSingleBit(h)) {
|
||||
tex_size.y() = PD::BitUtil::GetPow2((unsigned int)h);
|
||||
}
|
||||
|
||||
this->size.x() = (u16)w;
|
||||
this->size.y() = (u16)h;
|
||||
this->uv.x() = 0.0f;
|
||||
this->uv.y() = 1.0f;
|
||||
this->uv.z() = ((float)w / (float)tex_size.x());
|
||||
this->uv.w() = 1.0 - ((float)h / (float)tex_size.y());
|
||||
|
||||
// Texture Setup
|
||||
auto fltr = (filter == NEAREST ? GPU_NEAREST : GPU_LINEAR);
|
||||
auto tex_fmt = GetTexFmt(type);
|
||||
tex = new C3D_Tex;
|
||||
C3D_TexInit(tex, (u16)tex_size.x(), (u16)tex_size.y(), tex_fmt);
|
||||
C3D_TexSetFilter(tex, fltr, fltr);
|
||||
|
||||
memset(tex->data, 0, tex->size);
|
||||
|
||||
if (bpp == 3 || bpp == 4) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int dst_pos = ((((y >> 3) * ((int)tex_size.x() >> 3) + (x >> 3)) << 6) +
|
||||
((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) |
|
||||
((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) *
|
||||
bpp;
|
||||
int src_pos = (y * w + x) * bpp;
|
||||
|
||||
memcpy(&((u8*)tex->data)[dst_pos], &buf[src_pos], bpp);
|
||||
}
|
||||
}
|
||||
C3D_TexFlush(tex);
|
||||
} else if (bpp == 1) {
|
||||
C3D_TexLoadImage(tex, buf.data(), GPU_TEXFACE_2D, 0);
|
||||
}
|
||||
|
||||
tex->border = 0x00000000;
|
||||
C3D_TexSetWrap(tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
|
||||
}
|
||||
|
||||
void Texture::Delete() {
|
||||
if (tex) {
|
||||
C3D_TexDelete(tex);
|
||||
delete tex;
|
||||
tex = nullptr;
|
||||
size = vec2();
|
||||
uv = vec4(0.f, 1.f, 1.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::LoadFile(const std::string& path) {
|
||||
PD::TT::Scope st("texldr-" + path);
|
||||
Delete();
|
||||
int w = 0, h = 0, c = 0;
|
||||
u8* image = stbi_load(path.c_str(), &w, &h, &c, 4);
|
||||
PD::Assert(image != nullptr, "Unable to load image: " + path);
|
||||
if (w > 1024 || h > 1024) {
|
||||
stbi_image_free(image);
|
||||
PD::Error("Width or heigt is > 1024");
|
||||
return;
|
||||
}
|
||||
std::vector<u8> buf;
|
||||
if (c == 3) {
|
||||
stbi_image_free(image);
|
||||
image = stbi_load(path.c_str(), &w, &h, &c, 3);
|
||||
buf.resize(w * h * 4);
|
||||
PD::ImgConvert::RGB24toRGBA32(
|
||||
buf, std::vector<u8>(image, image + (w * h * 3)), w, h);
|
||||
} else {
|
||||
buf.assign(image, image + (w * h * 4));
|
||||
stbi_image_free(image);
|
||||
}
|
||||
MakeTex(buf, w, h);
|
||||
}
|
||||
|
||||
void Texture::LoadMemory(const std::vector<u8>& data) {
|
||||
Delete();
|
||||
int w, h, c;
|
||||
u8* image = stbi_load_from_memory(data.data(), data.size(), &w, &h, &c, 4);
|
||||
if (image == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (w > 1024 || h > 1024) {
|
||||
stbi_image_free(image);
|
||||
return;
|
||||
}
|
||||
std::vector<u8> buf;
|
||||
if (c == 3) {
|
||||
stbi_image_free(image);
|
||||
image = stbi_load_from_memory(data.data(), data.size(), &w, &h, &c, 3);
|
||||
buf.resize(w * h * 4);
|
||||
PD::ImgConvert::RGB24toRGBA32(
|
||||
buf, std::vector<u8>(image, image + (w * h * 3)), w, h);
|
||||
} else {
|
||||
buf.assign(image, image + (w * h * 4));
|
||||
stbi_image_free(image);
|
||||
}
|
||||
MakeTex(buf, w, h);
|
||||
}
|
||||
|
||||
void Texture::LoadPixels(const std::vector<u8>& pixels, int w, int h, Type type,
|
||||
Filter filter) {
|
||||
Delete();
|
||||
int bpp = GetBPP(type);
|
||||
if (w * h * bpp != (int)pixels.size()) {
|
||||
return;
|
||||
}
|
||||
std::vector<u8> cpy(pixels);
|
||||
MakeTex(cpy, w, h, type, filter);
|
||||
}
|
||||
} // namespace PD
|
@ -1,276 +0,0 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <malloc.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pd/Error.hpp>
|
||||
#include <pd/base/FileSystem.hpp>
|
||||
#include <pd/external/json.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
#include <pd/palladium.hpp>
|
||||
|
||||
/// Base ///
|
||||
PDFlags pd_flags = PDFlags_Default;
|
||||
static Palladium::Thread pdi_idb_server; // Protected
|
||||
std::string pdi_app_name;
|
||||
std::string pdi_config_path;
|
||||
nlohmann::json pdi_config;
|
||||
u8 pdi_console_model = 0;
|
||||
u8 pdi_system_region = CFG_REGION_USA;
|
||||
bool pdi_is_citra = false;
|
||||
bool pdi_settings = false;
|
||||
NVec2 pdi_hid_touch_pos;
|
||||
bool pdi_is_ndsp = false;
|
||||
bool pdi_running = false;
|
||||
std::stack<std::unique_ptr<Palladium::Scene>> Palladium::Scene::scenes;
|
||||
std::unique_ptr<Palladium::Scene> pdi_fade_scene;
|
||||
std::vector<std::unique_ptr<Palladium::Ovl>> pdi_overlays;
|
||||
unsigned int pdi_frames = 0;
|
||||
u64 pdi_last_time = 0;
|
||||
float pdi_framerate = 0.0f;
|
||||
unsigned int pdi_mt_color = 0xaa000000;
|
||||
unsigned int pdi_mt_txtcolor = 0xbbffffff;
|
||||
bool pdi_mt_screen;
|
||||
float pdi_mt_txtSize;
|
||||
bool pdi_metrikd = false;
|
||||
bool pdi_ftraced = false;
|
||||
u64 pdi_delta_time;
|
||||
u64 pdi_last_tm = 0;
|
||||
float pdi_dtm = 0.f;
|
||||
float pdi_time;
|
||||
bool pdi_fadeout = false, pdi_fadein = false, pdi_fadeout2 = false,
|
||||
pdi_fadein2 = false;
|
||||
int pdi_fadealpha = 0;
|
||||
int pdi_fadecolor = 0;
|
||||
bool pdi_wait_fade = false;
|
||||
bool pdi_fade_exit = false;
|
||||
bool pdi_fade_scene_wait = false;
|
||||
bool pdi_idb_running = false;
|
||||
bool pdi_graphics_on = false;
|
||||
float pd_draw2_tsm = 1.2f;
|
||||
bool pdi_amdt = false;
|
||||
void *pdi_soc_buf = nullptr;
|
||||
bool pdi_is_am_init = false;
|
||||
Palladium::Theme::Ref pdi_active_theme;
|
||||
bool pdi_lggrf = false;
|
||||
|
||||
/// Global ///
|
||||
// Outdated HidApi (HidV2Patched)
|
||||
u32 d7_hDown;
|
||||
u32 d7_hHeld;
|
||||
u32 d7_hUp;
|
||||
u32 d7_hRepeat; // Inofficial lol
|
||||
touchPosition d7_touch;
|
||||
|
||||
// Modern Global Api
|
||||
bool pdi_enable_scene_system = true;
|
||||
bool pdi_debugging = false;
|
||||
C3D_RenderTarget *pd_top;
|
||||
C3D_RenderTarget *pd_top_right;
|
||||
C3D_RenderTarget *pd_bottom;
|
||||
PDMetrikOverlayFlags pd_ovl_flags = PDMetrikOverlayFlags_Default;
|
||||
PDFTraceOverlayFlags pd_ftrace_ovl_flags = PDFTraceOverlayFlags_Default;
|
||||
|
||||
Palladium::Net::Error pdi_soc_init() {
|
||||
if (pdi_soc_buf != nullptr) {
|
||||
return 0;
|
||||
}
|
||||
pdi_soc_buf = memalign(0x1000, 0x100000);
|
||||
if (!pdi_soc_buf) {
|
||||
return Palladium::Net::Error_Memory;
|
||||
}
|
||||
Result ret = socInit((u32 *)pdi_soc_buf, 0x100000);
|
||||
if (R_FAILED(ret)) {
|
||||
free(pdi_soc_buf);
|
||||
return (
|
||||
(static_cast<Palladium::Net::Error>(ret) << 32) |
|
||||
static_cast<Palladium::Net::Error>(Palladium::Net::Error_CtrStatus));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pdi_soc_deinit() {
|
||||
if (pdi_soc_buf) {
|
||||
socExit();
|
||||
free(pdi_soc_buf);
|
||||
}
|
||||
pdi_soc_buf = nullptr;
|
||||
}
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
Logger() = default;
|
||||
virtual ~Logger() = default;
|
||||
|
||||
static void log(const std::string &prefix, const std::string &message) {
|
||||
std::cout << "[" << prefix << "]: " << message << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
#define pd_err(x) Logger::log("ERROR", x)
|
||||
#define pd_wrn(x) Logger::log("WARNING", x)
|
||||
|
||||
class tcp_server {
|
||||
public:
|
||||
tcp_server(const std::string &ip, int port) {
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
pd_err("Unable to create socket!");
|
||||
return;
|
||||
}
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = port;
|
||||
server.sin_addr.s_addr = inet_addr(ip.c_str());
|
||||
|
||||
e = bind(sockfd, (struct sockaddr *)&server, sizeof(server));
|
||||
if (e == -1) {
|
||||
pd_err("Unable to bind!");
|
||||
return;
|
||||
}
|
||||
e = listen(sockfd, 10);
|
||||
if (e == 0) {
|
||||
printf("[+]Listening...\n");
|
||||
} else {
|
||||
pd_err("Error in Binding");
|
||||
return;
|
||||
}
|
||||
addr_size = sizeof(new_addr);
|
||||
new_sock = accept(sockfd, (struct sockaddr *)&new_addr, &addr_size);
|
||||
std::cout << "Connected" << std::endl;
|
||||
}
|
||||
~tcp_server() {
|
||||
// Nothing here
|
||||
}
|
||||
|
||||
bool reconnect() {
|
||||
close(new_sock);
|
||||
new_sock = accept(sockfd, (struct sockaddr *)&new_addr, &addr_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t snd(void *ptr, size_t size) { return send(new_sock, ptr, size, 0); }
|
||||
|
||||
size_t rec(void *ptr, size_t size) { return recv(new_sock, ptr, size, 0); }
|
||||
|
||||
private:
|
||||
int e, sockfd, new_sock;
|
||||
struct sockaddr_in server, new_addr;
|
||||
socklen_t addr_size;
|
||||
};
|
||||
|
||||
#define stupid(x) &x, sizeof(x)
|
||||
#define pdi_reacttion(x) \
|
||||
{ \
|
||||
int code = x; \
|
||||
server.snd(stupid(code)); \
|
||||
}
|
||||
|
||||
struct pak32 {
|
||||
pak32() {}
|
||||
pak32(const std::string &n0, float n1, unsigned char n2, unsigned char n3,
|
||||
bool n4, bool n5, bool n6, float n7, float n8, float n9, float n10,
|
||||
unsigned int n11, unsigned int n12, unsigned int n13) {
|
||||
magic = 0x44772277;
|
||||
for (int i = 0; i < 64; i++) app_name[i] = (char)0;
|
||||
int l = n0.length();
|
||||
if (l > 64) l = 64;
|
||||
for (int i = 0; i < l; i++) app_name[i] = n0[i];
|
||||
framerate = n1;
|
||||
console_model = n2;
|
||||
system_region = n3;
|
||||
is_citra = n4;
|
||||
ndsp_support = n5;
|
||||
in_settings = n6;
|
||||
deltatime = n7;
|
||||
rtime = n8;
|
||||
cpu = n9;
|
||||
gpu = n10;
|
||||
mem_alloc = n11;
|
||||
mem_dalloc = n12;
|
||||
mem_ialloc = n13;
|
||||
}
|
||||
uint32_t magic;
|
||||
char app_name[64];
|
||||
float framerate;
|
||||
unsigned char console_model;
|
||||
unsigned char system_region;
|
||||
bool is_citra;
|
||||
bool ndsp_support;
|
||||
bool in_settings;
|
||||
float deltatime;
|
||||
float rtime;
|
||||
float cpu;
|
||||
float gpu;
|
||||
unsigned int mem_alloc;
|
||||
unsigned int mem_dalloc;
|
||||
unsigned int mem_ialloc;
|
||||
};
|
||||
|
||||
static bool pdi_idb_fp = false;
|
||||
|
||||
void KillIdbServer() {
|
||||
pdi_idb_fp = true;
|
||||
pdi_idb_server.join(100);
|
||||
}
|
||||
|
||||
void ServerThread(Palladium::Parameter param) {
|
||||
if (pdi_soc_buf == nullptr) return;
|
||||
pdi_idb_running = true;
|
||||
pdi_idb_fp = false;
|
||||
atexit(KillIdbServer);
|
||||
tcp_server server("0.0.0.0", 4727);
|
||||
int cmd = 0;
|
||||
while (!pdi_idb_fp) {
|
||||
size_t r = server.rec(&cmd, sizeof(int));
|
||||
if (r == 0) {
|
||||
server.reconnect();
|
||||
}
|
||||
if (cmd == 1) {
|
||||
pdi_reacttion(1);
|
||||
auto pak = pak32(
|
||||
pdi_app_name, pdi_framerate, pdi_console_model, pdi_system_region,
|
||||
pdi_is_citra, pdi_is_ndsp, pdi_settings, pdi_dtm, pdi_time,
|
||||
C3D_GetProcessingTime(), C3D_GetDrawingTime(),
|
||||
Palladium::Memory::GetTotalAllocated(),
|
||||
Palladium::Memory::GetTotalFreed(), Palladium::Memory::GetCurrent());
|
||||
server.snd(stupid(pak));
|
||||
} else if (cmd == 2) {
|
||||
pdi_reacttion(2);
|
||||
std::vector<Palladium::FileSystem::Entry> el =
|
||||
Palladium::FileSystem::GetDirContent("sdmc:/");
|
||||
size_t buf = el.size() * sizeof(Palladium::FileSystem::Entry);
|
||||
server.snd(stupid(buf));
|
||||
server.snd(el.data(), buf);
|
||||
|
||||
} else if (cmd == 3) {
|
||||
pdi_reacttion(3);
|
||||
Palladium::ExitApp();
|
||||
pdi_idb_fp = true;
|
||||
} else {
|
||||
pdi_reacttion(1234);
|
||||
}
|
||||
}
|
||||
pdi_idb_running = false;
|
||||
}
|
||||
|
||||
namespace Palladium {
|
||||
namespace IDB {
|
||||
void Start() {
|
||||
if (pdi_idb_running) return;
|
||||
pdi_idb_server.initialize(ServerThread);
|
||||
pdi_idb_server.start(true);
|
||||
}
|
||||
void Stop() {
|
||||
if (!pdi_idb_running) return;
|
||||
pdi_idb_fp = true;
|
||||
KillIdbServer();
|
||||
}
|
||||
void Restart() {
|
||||
Stop();
|
||||
Start();
|
||||
}
|
||||
} // namespace IDB
|
||||
} // namespace Palladium
|
38
source/maths/bit_util.cpp
Normal file
38
source/maths/bit_util.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/maths/bit_util.hpp>
|
||||
|
||||
namespace PD::BitUtil {
|
||||
bool IsSingleBit(u32 v) { return v && !(v & (v - 1)); }
|
||||
u32 GetPow2(u32 v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return (v >= 64 ? v : 64);
|
||||
}
|
||||
} // namespace PD::BitUtil
|
72
source/maths/color.cpp
Normal file
72
source/maths/color.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/maths/color.hpp>
|
||||
|
||||
namespace PD {
|
||||
// The Solution of the biggest performance issue
|
||||
// A Simple Lookup table
|
||||
static const std::map<char, int> HEX_DEC = {
|
||||
{'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5},
|
||||
{'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'a', 10}, {'b', 11},
|
||||
{'c', 12}, {'d', 13}, {'e', 14}, {'f', 15}, {'A', 10}, {'B', 11},
|
||||
{'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}};
|
||||
|
||||
Color& Color::Hex(const std::string& hex) {
|
||||
#ifdef PD_NO_SAFE_CODE
|
||||
/// Safetey check (not required if you programm well xd)
|
||||
if (hex.length() != 7 || hex.length() != 9 || hex.length() != 6 ||
|
||||
hex.length() != 8 || std::find_if(hex.begin(), hex.end(), [](char c) {
|
||||
return !std::isxdigit(c);
|
||||
}) != hex.end()) {
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
int offset = ((hex.length() == 7 || hex.length() == 9) ? 1 : 0);
|
||||
m_r = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
|
||||
offset += 2;
|
||||
m_g = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
|
||||
offset += 2;
|
||||
m_b = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
|
||||
offset += 2;
|
||||
if (hex.length() == 9) {
|
||||
m_a = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
|
||||
} else {
|
||||
m_a = 255;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string Color::Hex(bool rgba) const {
|
||||
std::stringstream s;
|
||||
s << "#";
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << m_r;
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << m_g;
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << m_b;
|
||||
if (rgba) {
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << m_a;
|
||||
}
|
||||
return s.str();
|
||||
}
|
||||
} // namespace PD
|
41
source/maths/img_convert.cpp
Normal file
41
source/maths/img_convert.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/maths/img_convert.hpp>
|
||||
|
||||
namespace PD::ImgConvert {
|
||||
void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int src = (y * w + x) * 3;
|
||||
int dst = (y * w + x) * 4;
|
||||
out[dst + 0] = in[src + 0];
|
||||
out[dst + 1] = in[src + 1];
|
||||
out[dst + 2] = in[src + 2];
|
||||
out[dst + 3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace PD::ImgConvert
|
117
source/nimg.cpp
117
source/nimg.cpp
@ -1,117 +0,0 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <pd/nimg.hpp>
|
||||
|
||||
// Use an Npi simplifier cause I am lazy
|
||||
#define reca_cc(x) reinterpret_cast<const char*>(x)
|
||||
#define reca_c(x) reinterpret_cast<char*>(x)
|
||||
#define pak32(q, w, e, r) \
|
||||
((((q)&0xff) << 0) | (((w)&0xff) << 8) | (((e)&0xff) << 16) | \
|
||||
(((r)&0xff) << 24))
|
||||
|
||||
// Stupid RLE Algorithm
|
||||
void npi_compress(std::vector<unsigned char>& ret,
|
||||
const std::vector<unsigned char>& in) {
|
||||
unsigned char counter = 1;
|
||||
unsigned char tmp = in[0];
|
||||
for (size_t i = 1; i < in.size(); ++i) {
|
||||
if (tmp == in[i]) {
|
||||
counter++;
|
||||
} else {
|
||||
ret.push_back(counter);
|
||||
ret.push_back(tmp);
|
||||
counter = 1;
|
||||
tmp = in[i];
|
||||
}
|
||||
if (counter == 255) {
|
||||
ret.push_back(counter);
|
||||
ret.push_back(tmp);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
if (counter > 0) {
|
||||
ret.push_back(counter);
|
||||
ret.push_back(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void npi_decompress(std::vector<unsigned char>& ret,
|
||||
const std::vector<unsigned char>& in) {
|
||||
// Size is sus
|
||||
if ((in.size() % 2) != 0) return;
|
||||
for (size_t i = 0; i < in.size(); i += 2) {
|
||||
int count = in[i];
|
||||
int value = in[i + 1];
|
||||
for (int c = 0; c < count; c++) {
|
||||
ret.push_back(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Palladium {
|
||||
nimg NIMG_Load(std::string path) {
|
||||
nimg res;
|
||||
std::ifstream fin(path, std::ios::in | std::ios::binary);
|
||||
// Check magic
|
||||
fin.read(reca_c(&res.magic), sizeof(uint32_t));
|
||||
if (res.magic != NPI_NIMG_) {
|
||||
std::cout << path << " is invalid!" << std::endl;
|
||||
return res;
|
||||
}
|
||||
// Read Information
|
||||
fin.read(reca_c(&res.width), sizeof(int));
|
||||
fin.read(reca_c(&res.height), sizeof(int));
|
||||
fin.read(reca_c(&res.format), sizeof(int));
|
||||
fin.read(reca_c(&res.compression), sizeof(int));
|
||||
// Read Pixeldata
|
||||
if (res.compression == 1) {
|
||||
std::vector<unsigned char> tb;
|
||||
int pb_size = 0;
|
||||
fin.read(reca_c(&pb_size), sizeof(int));
|
||||
tb.resize(pb_size);
|
||||
fin.read(reca_c(tb.data()), pb_size);
|
||||
npi_decompress(res.pixel_buffer, tb);
|
||||
} else {
|
||||
int pb_size = 0;
|
||||
fin.read(reca_c(&pb_size), sizeof(int));
|
||||
res.pixel_buffer.resize(pb_size);
|
||||
fin.read(reca_c(res.pixel_buffer.data()), pb_size);
|
||||
}
|
||||
|
||||
// Close stream
|
||||
fin.close();
|
||||
// Return the loadet imaeg
|
||||
return res;
|
||||
}
|
||||
|
||||
nimg NIMG_LoadFromMem(unsigned char* buffer, size_t bf_size) { return nimg(); }
|
||||
|
||||
void NIMG_Save(nimg image, std::string path) {
|
||||
std::ofstream fout(path);
|
||||
// Write Magic
|
||||
fout.write(reca_cc(&image.magic), sizeof(uint32_t));
|
||||
// Write Information
|
||||
fout.write(reca_cc(&image.width), sizeof(int));
|
||||
fout.write(reca_cc(&image.height), sizeof(int));
|
||||
fout.write(reca_cc(&image.format), sizeof(int));
|
||||
fout.write(reca_cc(&image.compression), sizeof(int));
|
||||
std::vector<unsigned char> test;
|
||||
// Write pixels
|
||||
if (image.compression == 1) {
|
||||
std::vector<unsigned char> tb;
|
||||
npi_compress(tb, image.pixel_buffer);
|
||||
int buf_szs = tb.size();
|
||||
fout.write(reca_cc(&buf_szs), sizeof(int)); // buf_size
|
||||
fout.write(reca_cc(tb.data()),
|
||||
tb.size()); // buffer
|
||||
} else {
|
||||
int buf_szs = image.pixel_buffer.size();
|
||||
fout.write(reca_cc(&buf_szs), sizeof(int)); // buf_size
|
||||
fout.write(reca_cc(image.pixel_buffer.data()),
|
||||
image.pixel_buffer.size()); // buffer
|
||||
}
|
||||
|
||||
// Close stream
|
||||
fout.close();
|
||||
}
|
||||
} // namespace Palladium
|
@ -1,917 +0,0 @@
|
||||
#include <pd/Hid.hpp> // Integate HidApi
|
||||
#include <pd/Lithium.hpp>
|
||||
#include <pd/Message.hpp>
|
||||
#include <pd/Overlays.hpp>
|
||||
#include <pd/ThemeEditor.hpp>
|
||||
#include <pd/UI7.hpp>
|
||||
#include <pd/palladium.hpp>
|
||||
|
||||
// Config 2
|
||||
#include <pd/external/json.hpp>
|
||||
#include <pd/internal_db.hpp>
|
||||
|
||||
// C++ includes
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <random>
|
||||
|
||||
#define DISPLAY_TRANSFER_FLAGS \
|
||||
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | \
|
||||
GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | \
|
||||
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
|
||||
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
|
||||
|
||||
void exit_romfs() { romfsExit(); }
|
||||
|
||||
// OVL FLAG ENTRY
|
||||
void OverlayFlag(PDMetrikOverlayFlags &flags, int flag, std::string name) {
|
||||
bool val = flags & flag;
|
||||
bool valb = val;
|
||||
UI7::Checkbox(name, val);
|
||||
if (val != valb) {
|
||||
if (val)
|
||||
flags |= flag;
|
||||
else
|
||||
flags &= ~flag;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Better Fader
|
||||
void Npifade() {
|
||||
if (pdi_fadein) {
|
||||
if (pdi_fadealpha < 255) {
|
||||
if ((int)pdi_fadealpha + 3 > 255) {
|
||||
pdi_fadealpha = 255;
|
||||
} else {
|
||||
pdi_fadealpha += 3;
|
||||
}
|
||||
} else {
|
||||
pdi_fadein = false;
|
||||
}
|
||||
} else if (pdi_fadeout) {
|
||||
if (pdi_fadealpha > 0) {
|
||||
if ((int)pdi_fadealpha - 3 < 0) {
|
||||
pdi_fadealpha = 0;
|
||||
} else {
|
||||
pdi_fadealpha -= 3;
|
||||
}
|
||||
} else {
|
||||
pdi_fadeout = false;
|
||||
}
|
||||
} else {
|
||||
if (pdi_wait_fade) pdi_wait_fade = false;
|
||||
if (pdi_fade_exit) pdi_running = false;
|
||||
if (pdi_fade_scene_wait) {
|
||||
Palladium::Scene::scenes.push(std::move(pdi_fade_scene));
|
||||
pdi_fade_scene_wait = false;
|
||||
Palladium::FadeIn();
|
||||
}
|
||||
// No fade
|
||||
}
|
||||
/*if (pdi_fadein || pdi_fadeout) {
|
||||
LI::OnScreen(LIScreen_Top);
|
||||
LI::AddRect(NVec2(0, 0), NVec2(400, 240),
|
||||
((pdi_fadealpha << 24) | 0x00000000));
|
||||
LI::OnScreen(LIScreen_Bottom);
|
||||
LI::AddRect(NVec2(0, 0), NVec2(320, 240),
|
||||
((pdi_fadealpha << 24) | 0x00000000));
|
||||
}*/
|
||||
}
|
||||
|
||||
void pdi_init_input() {
|
||||
Palladium::Hid::RegTouchCoords(pdi_hid_touch_pos);
|
||||
Palladium::Hid::RegKeyDown(d7_hDown);
|
||||
Palladium::Hid::RegKeyHeld(d7_hHeld);
|
||||
Palladium::Hid::RegKeyUp(d7_hUp);
|
||||
Palladium::Hid::RegKeyRepeat(d7_hRepeat);
|
||||
Palladium::Hid::RegKeyEvent("touch", KEY_TOUCH);
|
||||
// Default Buttons
|
||||
Palladium::Hid::RegKeyEvent("confirm", KEY_A);
|
||||
Palladium::Hid::RegKeyEvent("cancel", KEY_B);
|
||||
Palladium::Hid::RegKeyEvent("spec2", KEY_X);
|
||||
Palladium::Hid::RegKeyEvent("spec3", KEY_Y);
|
||||
Palladium::Hid::RegKeyEvent("options", KEY_SELECT);
|
||||
Palladium::Hid::RegKeyEvent("spec1", KEY_START);
|
||||
// Dpad only
|
||||
Palladium::Hid::RegKeyEvent("dright", KEY_DRIGHT);
|
||||
Palladium::Hid::RegKeyEvent("dleft", KEY_DLEFT);
|
||||
Palladium::Hid::RegKeyEvent("dup", KEY_DUP);
|
||||
Palladium::Hid::RegKeyEvent("ddown", KEY_DDOWN);
|
||||
// D + Cpad
|
||||
Palladium::Hid::RegKeyEvent("right", KEY_RIGHT);
|
||||
Palladium::Hid::RegKeyEvent("left", KEY_LEFT);
|
||||
Palladium::Hid::RegKeyEvent("up", KEY_UP);
|
||||
Palladium::Hid::RegKeyEvent("down", KEY_DOWN);
|
||||
// Back keys
|
||||
Palladium::Hid::RegKeyEvent("rt1", KEY_R);
|
||||
Palladium::Hid::RegKeyEvent("lt1", KEY_L);
|
||||
Palladium::Hid::RegKeyEvent("rt2", KEY_ZL);
|
||||
Palladium::Hid::RegKeyEvent("lt2", KEY_ZR);
|
||||
// Key by their names
|
||||
Palladium::Hid::RegKeyEvent("A", KEY_A);
|
||||
Palladium::Hid::RegKeyEvent("B", KEY_B);
|
||||
Palladium::Hid::RegKeyEvent("X", KEY_X);
|
||||
Palladium::Hid::RegKeyEvent("Y", KEY_Y);
|
||||
Palladium::Hid::RegKeyEvent("L", KEY_L);
|
||||
Palladium::Hid::RegKeyEvent("R", KEY_R);
|
||||
Palladium::Hid::RegKeyEvent("ZR", KEY_ZR);
|
||||
Palladium::Hid::RegKeyEvent("ZL", KEY_ZL);
|
||||
Palladium::Hid::RegKeyEvent("START", KEY_START);
|
||||
Palladium::Hid::RegKeyEvent("SELECT", KEY_SELECT);
|
||||
Palladium::Hid::RegKeyEvent("DUP", KEY_DUP);
|
||||
Palladium::Hid::RegKeyEvent("DDOWN", KEY_DDOWN);
|
||||
Palladium::Hid::RegKeyEvent("DLEFT", KEY_DRIGHT);
|
||||
Palladium::Hid::RegKeyEvent("DRIGHT", KEY_DLEFT);
|
||||
}
|
||||
|
||||
void pdi_init_config() {
|
||||
pdi_config_path = Palladium::GetAppDirectory();
|
||||
std::filesystem::create_directories(pdi_config_path.c_str());
|
||||
std::filesystem::create_directories("sdmc:/Palladium/Reports");
|
||||
bool renew = false;
|
||||
|
||||
if (Palladium::FS::FileExist(pdi_config_path + "/config.rc7")) {
|
||||
std::fstream cfg_ldr(pdi_config_path + "/config.rc7", std::ios::in);
|
||||
cfg_ldr >> pdi_config;
|
||||
cfg_ldr.close();
|
||||
std::string version = pdi_config["info"]["version"].get<std::string>();
|
||||
if (version != CFGVER) renew = true;
|
||||
}
|
||||
|
||||
if (!Palladium::FS::FileExist(pdi_config_path + "/config.rc7") || renew) {
|
||||
if (renew) {
|
||||
std::fstream cfg_ldr(pdi_config_path + "/config.rc7", std::ios::in);
|
||||
cfg_ldr >> pdi_config;
|
||||
cfg_ldr.close();
|
||||
}
|
||||
pdi_config.clear();
|
||||
pdi_config["info"]["version"] = CFGVER;
|
||||
pdi_config["info"]["Palladiumver"] = PDVSTRING;
|
||||
pdi_config["metrik-settings"]["show"] = false;
|
||||
pdi_config["metrik-settings"]["Screen"] = true;
|
||||
pdi_config["metrik-settings"]["Text"] = 0xffffffff;
|
||||
pdi_config["metrik-settings"]["Bg"] = 0xaa000000;
|
||||
pdi_config["metrik-settings"]["Size"] = 0.7f;
|
||||
pdi_config["metrik-settings"]["config"] = PDMetrikOverlayFlags_Default;
|
||||
std::fstream cfg_wrt(pdi_config_path + "/config.rc7", std::ios::out);
|
||||
cfg_wrt << pdi_config.dump(4);
|
||||
cfg_wrt.close();
|
||||
}
|
||||
std::fstream cfg_ldr(pdi_config_path + "/config.rc7", std::ios::in);
|
||||
cfg_ldr >> pdi_config;
|
||||
cfg_ldr.close();
|
||||
|
||||
pdi_metrikd = pdi_config["metrik-settings"]["show"].get<bool>();
|
||||
pdi_mt_txtSize = pdi_config["metrik-settings"]["Size"].get<float>();
|
||||
pdi_mt_screen = pdi_config["metrik-settings"]["Screen"].get<bool>();
|
||||
pdi_mt_txtcolor = pdi_config["metrik-settings"]["Text"].get<unsigned int>();
|
||||
pdi_mt_color = pdi_config["metrik-settings"]["Bg"].get<unsigned int>();
|
||||
pd_ovl_flags = pdi_config["metrik-settings"]["config"].get<int>();
|
||||
|
||||
if (pdi_metrikd)
|
||||
Palladium::AddOvl(std::make_unique<Palladium::Ovl_Metrik>(
|
||||
&pdi_metrikd, &pdi_mt_screen, &pdi_mt_color, &pdi_mt_txtcolor,
|
||||
&pdi_mt_txtSize));
|
||||
}
|
||||
|
||||
void pdi_init_theme() {
|
||||
if (pdi_config_path == "") {
|
||||
pdi_config_path = "sdmc:/Palladium/Apps/";
|
||||
pdi_config_path += pdi_app_name;
|
||||
}
|
||||
std::string path = pdi_config_path + "/themes";
|
||||
std::filesystem::create_directories(path.c_str());
|
||||
bool renew = false;
|
||||
|
||||
if (Palladium::FS::FileExist(path + "/Palladium.theme")) {
|
||||
std::fstream cfg_ldr(path + "/Palladium.theme", std::ios::in);
|
||||
nlohmann::json js;
|
||||
cfg_ldr >> js;
|
||||
cfg_ldr.close();
|
||||
std::string version = js["version"].get<std::string>();
|
||||
if (version != THEMEVER) renew = true;
|
||||
}
|
||||
|
||||
if (!Palladium::FS::FileExist(path + "/Palladium.theme") || renew) {
|
||||
pdi_amdt = true;
|
||||
Palladium::ThemeActive()->Save(path + "/Palladium.theme");
|
||||
pdi_amdt = false;
|
||||
}
|
||||
}
|
||||
|
||||
float Palladium::GetDeltaTime() { return pdi_dtm; }
|
||||
|
||||
void Palladium::Init::NdspFirm() {
|
||||
if (access("sdmc:/3ds/dspfirm.cdc", F_OK) != -1) {
|
||||
ndspInit();
|
||||
atexit(ndspExit);
|
||||
pdi_is_ndsp = true;
|
||||
} else {
|
||||
Palladium::PushMessage(Palladium::Message(
|
||||
"Palladium", "dspfirm.cdc not found!\nUnable to play sounds!"));
|
||||
}
|
||||
}
|
||||
|
||||
void Palladium::Scene::doUpdate() {
|
||||
Ftrace::ScopedTrace st("pd-core", f2s(Scene::doUpdate));
|
||||
if (!Palladium::Scene::scenes.empty())
|
||||
Palladium::Scene::scenes.top()->Update();
|
||||
}
|
||||
|
||||
void Palladium::Scene::Load(std::unique_ptr<Scene> scene, bool fade) {
|
||||
if (fade) {
|
||||
Palladium::FadeOut();
|
||||
pdi_fade_scene = std::move(scene);
|
||||
pdi_fade_scene_wait = true;
|
||||
} else
|
||||
Scene::scenes.push(std::move(scene));
|
||||
}
|
||||
|
||||
void Palladium::Scene::Back() {
|
||||
if (Palladium::Scene::scenes.size() > 0) Palladium::Scene::scenes.pop();
|
||||
}
|
||||
|
||||
void frameloop() {
|
||||
pdi_frames++;
|
||||
pdi_delta_time = osGetTime() - pdi_last_time;
|
||||
if (pdi_delta_time >= 1000) {
|
||||
pdi_framerate = pdi_frames / (pdi_delta_time / 1000.0f) + 1;
|
||||
pdi_frames = 0;
|
||||
pdi_last_time = osGetTime();
|
||||
}
|
||||
}
|
||||
float getframerate() { return pdi_framerate; }
|
||||
|
||||
std::string Palladium::GetFramerate() {
|
||||
return (std::to_string((int)pdi_framerate).substr(0, 2));
|
||||
}
|
||||
|
||||
bool Palladium::MainLoop() {
|
||||
if (!aptMainLoop()) return false;
|
||||
// Deltatime
|
||||
uint64_t currentTime = svcGetSystemTick();
|
||||
pdi_dtm = static_cast<float>(currentTime - pdi_last_tm) / TICKS_PER_MSEC;
|
||||
pdi_time += pdi_dtm * 0.001f;
|
||||
pdi_last_tm = currentTime;
|
||||
|
||||
hidScanInput();
|
||||
d7_hDown = hidKeysDown();
|
||||
d7_hUp = hidKeysUp();
|
||||
d7_hHeld = hidKeysHeld();
|
||||
// Inofficial
|
||||
d7_hRepeat = hidKeysDownRepeat();
|
||||
hidTouchRead(&d7_touch);
|
||||
Hid::Update();
|
||||
pdi_hid_touch_pos = NVec2(d7_touch.px, d7_touch.py);
|
||||
|
||||
Palladium::Ftrace::End("pd-core", f2s(MainLoop));
|
||||
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
||||
Palladium::Ftrace::Beg("pd-core", f2s(MainLoop));
|
||||
|
||||
C3D_RenderTargetClear(pd_top, C3D_CLEAR_ALL, 0x00000000, 0);
|
||||
C3D_RenderTargetClear(pd_top_right, C3D_CLEAR_ALL, 0x00000000, 0);
|
||||
C3D_RenderTargetClear(pd_bottom, C3D_CLEAR_ALL, 0x00000000, 0);
|
||||
frameloop();
|
||||
if (pdi_enable_scene_system) {
|
||||
Palladium::Scene::doUpdate();
|
||||
}
|
||||
return pdi_running;
|
||||
}
|
||||
|
||||
void Palladium::Init::Graphics() {
|
||||
// C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
// C2D_Init((size_t)pd_max_objects);
|
||||
// C2D_Prepare();
|
||||
// pd_top = C2D_CreateScreenTarget(GFX_TOP, GFX_LEFT);
|
||||
// pd_top_right = C2D_CreateScreenTarget(GFX_TOP, GFX_RIGHT);
|
||||
// pd_bottom = C2D_CreateScreenTarget(GFX_BOTTOM, GFX_LEFT);
|
||||
}
|
||||
|
||||
Result Palladium::Init::Main(std::string app_name) {
|
||||
Palladium::Ftrace::ScopedTrace st("pd-core", f2s(Init::Main));
|
||||
pdi_app_name = app_name;
|
||||
|
||||
pdi_enable_scene_system = (pd_flags & PDFlags_SceneSystem);
|
||||
|
||||
gfxInitDefault();
|
||||
atexit(gfxExit);
|
||||
// Speedup
|
||||
osSetSpeedupEnable(true);
|
||||
// consoleInit(GFX_TOP, NULL);
|
||||
cfguInit();
|
||||
atexit(cfguExit);
|
||||
CFGU_SecureInfoGetRegion(&pdi_system_region);
|
||||
CFGU_GetSystemModel(&pdi_console_model);
|
||||
|
||||
aptInit();
|
||||
atexit(aptExit);
|
||||
romfsInit();
|
||||
|
||||
pdi_init_config();
|
||||
|
||||
pdi_active_theme = Theme::New();
|
||||
pdi_active_theme->Default();
|
||||
|
||||
auto ret = pdi_soc_init();
|
||||
if (ret) {
|
||||
Palladium::PushMessage("Palladium", "Failed to\nInit Soc!");
|
||||
} else {
|
||||
atexit(pdi_soc_deinit);
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(amInit())) {
|
||||
atexit(amExit);
|
||||
pdi_is_am_init = true;
|
||||
}
|
||||
|
||||
Hardware::Initialisize();
|
||||
|
||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
atexit(C3D_Fini);
|
||||
|
||||
pd_top =
|
||||
C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(pd_top, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
||||
pd_top_right =
|
||||
C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(pd_top_right, GFX_TOP, GFX_RIGHT,
|
||||
DISPLAY_TRANSFER_FLAGS);
|
||||
pd_bottom =
|
||||
C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(pd_bottom, GFX_BOTTOM, GFX_LEFT,
|
||||
DISPLAY_TRANSFER_FLAGS);
|
||||
LI::Init();
|
||||
atexit(LI::Exit);
|
||||
atexit(exit_romfs);
|
||||
|
||||
pdi_graphics_on = true;
|
||||
pdi_last_tm = svcGetSystemTick();
|
||||
|
||||
pdi_init_input();
|
||||
pdi_init_theme();
|
||||
UI7::Init();
|
||||
atexit(UI7::Deinit);
|
||||
pdi_running = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result Palladium::Init::Minimal(std::string app_name) {
|
||||
Palladium::Ftrace::ScopedTrace st("pd-core", f2s(Init::Minimal));
|
||||
pdi_app_name = app_name;
|
||||
|
||||
pdi_enable_scene_system = (pd_flags & PDFlags_SceneSystem);
|
||||
|
||||
gfxInitDefault();
|
||||
atexit(gfxExit);
|
||||
romfsInit();
|
||||
|
||||
pdi_init_config();
|
||||
|
||||
pdi_active_theme = Theme::New();
|
||||
pdi_active_theme->Default();
|
||||
|
||||
auto ret = pdi_soc_init();
|
||||
if (ret) {
|
||||
Palladium::PushMessage("Palladium", "Failed to\nInit Soc!");
|
||||
} else {
|
||||
atexit(pdi_soc_deinit);
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(amInit())) {
|
||||
atexit(amExit);
|
||||
pdi_is_am_init = true;
|
||||
}
|
||||
|
||||
Hardware::Initialisize();
|
||||
|
||||
osSetSpeedupEnable(true);
|
||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
atexit(C3D_Fini);
|
||||
|
||||
pd_top =
|
||||
C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(pd_top, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
||||
pd_top_right =
|
||||
C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(pd_top_right, GFX_TOP, GFX_RIGHT,
|
||||
DISPLAY_TRANSFER_FLAGS);
|
||||
pd_bottom =
|
||||
C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(pd_bottom, GFX_BOTTOM, GFX_LEFT,
|
||||
DISPLAY_TRANSFER_FLAGS);
|
||||
LI::Init();
|
||||
atexit(LI::Exit);
|
||||
atexit(exit_romfs);
|
||||
|
||||
pdi_graphics_on = true;
|
||||
|
||||
// Check if citra
|
||||
s64 citracheck = 0;
|
||||
svcGetSystemInfo(&citracheck, 0x20000, 0);
|
||||
pdi_is_citra = citracheck ? true : false;
|
||||
|
||||
pdi_init_input();
|
||||
pdi_init_theme();
|
||||
UI7::Init();
|
||||
atexit(UI7::Deinit);
|
||||
pdi_running = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result Palladium::Init::Reload() {
|
||||
// pdi_graphics_on = false;
|
||||
// C3D_Fini();
|
||||
// C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
// pdi_graphics_on = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Palladium::ExitApp() {
|
||||
if (pdi_wait_fade) {
|
||||
pdi_fade_exit = true;
|
||||
} else
|
||||
pdi_running = false;
|
||||
}
|
||||
|
||||
int Palladium::GetRandomInt(int b, int e) {
|
||||
std::default_random_engine generator;
|
||||
std::uniform_int_distribution<int> distribution(b, e);
|
||||
int r = distribution(generator);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool Palladium::FS::FileExist(const std::string &path) {
|
||||
return std::filesystem::exists(path) &&
|
||||
std::filesystem::is_regular_file(path);
|
||||
}
|
||||
|
||||
int Palladium::GetFps() { return (int)pdi_framerate; }
|
||||
|
||||
bool Palladium::IsNdspInit() { return pdi_is_ndsp; }
|
||||
|
||||
void OvlHandler() {
|
||||
Palladium::Ftrace::ScopedTrace st("pd-core", f2s(OvlHandler));
|
||||
for (size_t i = 0; i < pdi_overlays.size(); i++) {
|
||||
pdi_overlays[i]->Draw();
|
||||
pdi_overlays[i]->Logic();
|
||||
if (pdi_overlays[i]->IsKilled())
|
||||
pdi_overlays.erase(pdi_overlays.begin() + i);
|
||||
}
|
||||
}
|
||||
|
||||
void Palladium::FrameEnd() {
|
||||
Ftrace::ScopedTrace st("pd-core", f2s(FrameEnd));
|
||||
C3D_FrameBegin(2);
|
||||
if (!pdi_enable_scene_system && pdi_settings) {
|
||||
Palladium::Scene::doUpdate();
|
||||
}
|
||||
UI7::Update();
|
||||
UI7::Debug();
|
||||
// Use Heigh Layer for Overlays
|
||||
LI::Layer(LI::Layer() + 100);
|
||||
Palladium::ProcessMessages();
|
||||
OvlHandler();
|
||||
Npifade();
|
||||
LI::Render(pd_top, pd_bottom);
|
||||
C3D_FrameEnd(0);
|
||||
}
|
||||
|
||||
Palladium::RSettings::RSettings() {
|
||||
// Palladium Settings is designed for
|
||||
// System Font
|
||||
tmp_txt = LI::GetTextScale();
|
||||
LI::DefaultTextScale();
|
||||
Palladium::FadeIn();
|
||||
std::fstream cfg_ldr(pdi_config_path + "/config.rc7", std::ios::in);
|
||||
cfg_ldr >> pdi_config;
|
||||
cfg_ldr.close();
|
||||
pdi_settings = true;
|
||||
statemtold = pdi_metrikd;
|
||||
stateftold = pdi_ftraced;
|
||||
}
|
||||
|
||||
Palladium::RSettings::~RSettings() { LI::SetTextScale(tmp_txt); }
|
||||
|
||||
std::vector<std::string> StrHelper(std::string input) {
|
||||
std::string ss(input);
|
||||
std::istringstream in(ss);
|
||||
std::vector<std::string> test1;
|
||||
|
||||
std::copy(std::istream_iterator<std::string>(in),
|
||||
std::istream_iterator<std::string>(), std::back_inserter(test1));
|
||||
return test1;
|
||||
}
|
||||
|
||||
void Palladium::RSettings::Update() {
|
||||
// Rendering / UI Logic
|
||||
/// TODO: Update code for new system
|
||||
if (m_state == RSETTINGS) {
|
||||
LI::OnScreen(false);
|
||||
if (UI7::BeginMenu("Palladium -> Settings")) {
|
||||
UI7::SetCursorPos(NVec2(395, 2));
|
||||
UI7::Label(PDVSTRING, PDTextFlags_AlignRight);
|
||||
UI7::RestoreCursor();
|
||||
UI7::Label("Config Version: " + std::string(CFGVER));
|
||||
UI7::Label("App: " + pdi_app_name);
|
||||
UI7::Label("Palladium: " + std::string(PDVSTRING));
|
||||
UI7::Label("Citra: " + std::string(pdi_is_citra ? "true" : "false"));
|
||||
UI7::Label("Current: " + std::to_string(Palladium::Memory::GetCurrent()) +
|
||||
"b");
|
||||
UI7::Label("Delta: " + std::to_string(Palladium::GetDeltaTime()));
|
||||
UI7::Label("Time: " + std::to_string(Palladium::GetTime()));
|
||||
UI7::Label("Kbd test: " + kbd_test);
|
||||
UI7::EndMenu();
|
||||
}
|
||||
LI::OnScreen(true);
|
||||
if (UI7::BeginMenu("Press B to go back!")) {
|
||||
if (UI7::Button("FTrace")) {
|
||||
shared_request[0x00000001] = RFTRACE;
|
||||
}
|
||||
if (UI7::Button("UI7")) {
|
||||
shared_request[0x00000001] = RUI7;
|
||||
}
|
||||
UI7::SameLine();
|
||||
if (UI7::Button("Font")) {
|
||||
shared_request[0x00000001] = RFV;
|
||||
}
|
||||
if (UI7::Button("Overlays")) {
|
||||
shared_request[0x00000001] = ROVERLAYS;
|
||||
}
|
||||
if (UI7::Button("IDB")) {
|
||||
shared_request[0x00000001] = RIDB;
|
||||
}
|
||||
if (UI7::Button("ThemeEditor")) {
|
||||
Palladium::LoadThemeEditor();
|
||||
}
|
||||
if (UI7::Button("Back")) {
|
||||
shared_request[0x00000002] = 1U;
|
||||
}
|
||||
if (UI7::Button("Keyboard")) {
|
||||
shared_request[0x00000003] = 1U;
|
||||
}
|
||||
UI7::EndMenu();
|
||||
}
|
||||
|
||||
} else if (m_state == RIDB) {
|
||||
LI::OnScreen(false);
|
||||
if (UI7::BeginMenu("Palladium -> Debugger")) {
|
||||
UI7::SetCursorPos(NVec2(395, 2));
|
||||
UI7::Label(PDVSTRING, PDTextFlags_AlignRight);
|
||||
UI7::RestoreCursor();
|
||||
UI7::Label("Server Running: " +
|
||||
std::string(pdi_idb_running ? "true" : "false"));
|
||||
UI7::EndMenu();
|
||||
}
|
||||
LI::OnScreen(true);
|
||||
if (UI7::BeginMenu("Press B to go back!")) {
|
||||
if (UI7::Button("Start Server")) {
|
||||
Palladium::IDB::Start();
|
||||
}
|
||||
UI7::SameLine();
|
||||
if (UI7::Button("Stop Server")) {
|
||||
Palladium::IDB::Stop();
|
||||
}
|
||||
UI7::SameLine();
|
||||
if (UI7::Button("Restart Server")) {
|
||||
Palladium::IDB::Restart();
|
||||
}
|
||||
|
||||
UI7::EndMenu();
|
||||
}
|
||||
|
||||
} else if (m_state == RFTRACE) {
|
||||
LI::OnScreen(false);
|
||||
auto list = UI7::GetBackgroundList();
|
||||
list->Layer(10);
|
||||
int lrb = list->Layer();
|
||||
// Draw Top Screen Into Background DrawList
|
||||
list->AddRectangle(NVec2(0, 0), NVec2(400, 240), PDColor_Background);
|
||||
list->AddRectangle(NVec2(0, 0), NVec2(400, 20), PDColor_Header);
|
||||
list->Layer(lrb + 1);
|
||||
list->AddText(NVec2(5, 2), "Palladium -> FTrace",
|
||||
Palladium::ThemeActive()->AutoText(PDColor_Header));
|
||||
list->AddText(NVec2(395, 2), PDVSTRING,
|
||||
Palladium::ThemeActive()->AutoText(PDColor_Header),
|
||||
PDTextFlags_AlignRight);
|
||||
list->Layer(lrb);
|
||||
list->AddRectangle(NVec2(0, 220), NVec2(400, 20),
|
||||
Palladium::ThemeActive()->Get(PDColor_Header));
|
||||
list->Layer(lrb + 1);
|
||||
list->AddText(NVec2(5, 222),
|
||||
"Traces: " + std::to_string(ftrace_index + 1) + "/" +
|
||||
std::to_string(Palladium::Ftrace::pd_traces.size()),
|
||||
Palladium::ThemeActive()->AutoText(PDColor_Header));
|
||||
list->Layer(lrb);
|
||||
list->AddRectangle(NVec2(0, 20), NVec2(400, 20), PDColor_TextDisabled);
|
||||
list->Layer(lrb + 1);
|
||||
list->AddText(NVec2(5, 22), "Function:",
|
||||
Palladium::ThemeActive()->AutoText(PDColor_TextDisabled));
|
||||
list->AddText(NVec2(395, 22), "Time (ms):",
|
||||
Palladium::ThemeActive()->AutoText(PDColor_TextDisabled),
|
||||
PDTextFlags_AlignRight);
|
||||
list->Layer(lrb);
|
||||
// List Bg
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if ((i % 2 == 0))
|
||||
list->AddRectangle(NVec2(0, 40 + (i)*15), NVec2(400, 15),
|
||||
PDColor_List0);
|
||||
else
|
||||
list->AddRectangle(NVec2(0, 40 + (i)*15), NVec2(400, 15),
|
||||
PDColor_List1);
|
||||
}
|
||||
|
||||
Palladium::Ftrace::Beg("PDft", "display_traces");
|
||||
int start_index = ftrace_index < 11 ? 0 : ftrace_index - 11;
|
||||
auto it = Palladium::Ftrace::pd_traces.begin();
|
||||
std::advance(it, start_index);
|
||||
int ix = start_index;
|
||||
std::string _fkey__ = "0";
|
||||
|
||||
while (ix < (int)Palladium::Ftrace::pd_traces.size() &&
|
||||
ix < start_index + 12 && it != Palladium::Ftrace::pd_traces.end()) {
|
||||
if (ix == ftrace_index) {
|
||||
_fkey__ = it->first;
|
||||
list->Layer(lrb + 1);
|
||||
list->AddRectangle(NVec2(0, 40 + (ix - start_index) * 15),
|
||||
NVec2(400, 15), PDColor_Selector);
|
||||
}
|
||||
list->Layer(lrb + 2);
|
||||
auto clr = ix == ftrace_index
|
||||
? PDColor_Selector
|
||||
: (ix % 2 == 0 ? PDColor_List0 : PDColor_List1);
|
||||
list->AddText(NVec2(5, 40 + (ix - start_index) * 15),
|
||||
it->second.func_name,
|
||||
Palladium::ThemeActive()->AutoText(clr));
|
||||
list->AddText(NVec2(395, 40 + (ix - start_index) * 15),
|
||||
Palladium::MsTimeFmt(it->second.time_of),
|
||||
Palladium::ThemeActive()->AutoText(clr),
|
||||
PDTextFlags_AlignRight);
|
||||
++it;
|
||||
++ix;
|
||||
}
|
||||
|
||||
Palladium::Ftrace::End("PDft", "display_traces");
|
||||
|
||||
LI::OnScreen(true);
|
||||
if (UI7::BeginMenu("Press B to go back!")) {
|
||||
auto jt = Palladium::Ftrace::pd_traces.begin();
|
||||
std::advance(jt, ftrace_index);
|
||||
UI7::Label("Group: " + jt->second.group);
|
||||
UI7::Label("Function: " + jt->second.func_name);
|
||||
UI7::Checkbox("In Overlay", jt->second.is_ovl);
|
||||
UI7::Label("Time: " + Palladium::MsTimeFmt(jt->second.time_of));
|
||||
UI7::Label("TS: " + std::to_string(jt->second.time_start));
|
||||
UI7::Label("TE: " + std::to_string(jt->second.time_end));
|
||||
UI7::Label("SVC_Stk: " + std::to_string(svcGetSystemTick()));
|
||||
UI7::Label("Last 60 frames:");
|
||||
UI7::Label("Max: " + Palladium::MsTimeFmt(jt->second.ts.GetMax()));
|
||||
UI7::Label("Min: " + Palladium::MsTimeFmt(jt->second.ts.GetMax()));
|
||||
UI7::Label("Avg: " + Palladium::MsTimeFmt(jt->second.ts.GetMax()));
|
||||
UI7::EndMenu();
|
||||
}
|
||||
} else if (m_state == RUI7) {
|
||||
LI::OnScreen(false);
|
||||
if (UI7::BeginMenu("Palladium -> UI7")) {
|
||||
UI7::SetCursorPos(NVec2(395, 2));
|
||||
UI7::Label(PDVSTRING, PDTextFlags_AlignRight);
|
||||
UI7::RestoreCursor();
|
||||
UI7::Label("Time: " + std::to_string(UI7::GetTime()));
|
||||
UI7::Label("Delta: " + std::to_string(UI7::GetDeltaTime()));
|
||||
UI7::Label("Hid Down Touch: " +
|
||||
std::to_string(Hid::IsEvent("touch", Hid::Down)));
|
||||
UI7::Label("Hid Held Touch: " +
|
||||
std::to_string(Hid::IsEvent("touch", Hid::Held)));
|
||||
UI7::Label("Hid Up Touch: " +
|
||||
std::to_string(Hid::IsEvent("touch", Hid::Up)));
|
||||
UI7::Label("Touch Pos: " + std::to_string(Hid::GetTouchPosition().x()) +
|
||||
", " + std::to_string(Hid::GetTouchPosition().y()));
|
||||
UI7::Label(
|
||||
"Touch Last Pos: " + std::to_string(Hid::GetLastTouchPosition().x()) +
|
||||
", " + std::to_string(Hid::GetLastTouchPosition().y()));
|
||||
UI7::Label(
|
||||
"Touch Down Pos: " + std::to_string(Hid::GetTouchDownPosition().x()) +
|
||||
", " + std::to_string(Hid::GetTouchDownPosition().y()));
|
||||
UI7::EndMenu();
|
||||
}
|
||||
|
||||
LI::OnScreen(true);
|
||||
if (UI7::BeginMenu("Press B to go back!", NVec2(),
|
||||
UI7MenuFlags_Scrolling)) {
|
||||
if (UI7::Button("Go back")) {
|
||||
/// Request a state switch to state RSETTINGS
|
||||
shared_request[0x00000001] = RSETTINGS;
|
||||
}
|
||||
UI7::Checkbox("Debug", UI7::IsDebugging());
|
||||
UI7::Checkbox("ShowMenuInfo", UI7::DebugMenu());
|
||||
UI7::EndMenu();
|
||||
}
|
||||
} else if (m_state == ROVERLAYS) {
|
||||
LI::OnScreen(false);
|
||||
if (UI7::BeginMenu("Palladium -> Overlays")) {
|
||||
UI7::SetCursorPos(NVec2(395, 2));
|
||||
UI7::Label(PDVSTRING, PDTextFlags_AlignRight);
|
||||
UI7::RestoreCursor();
|
||||
UI7::Label("Metrik Overlay: " + mtovlstate);
|
||||
UI7::Label("Metrik Screen: " + mtscreenstate);
|
||||
UI7::EndMenu();
|
||||
}
|
||||
|
||||
LI::OnScreen(true);
|
||||
if (UI7::BeginMenu("Press B to go back!", NVec2(),
|
||||
UI7MenuFlags_Scrolling)) {
|
||||
if (UI7::Button("Go back")) {
|
||||
/// Request a state switch to state RSETTINGS
|
||||
shared_request[0x00000001] = RSETTINGS;
|
||||
}
|
||||
UI7::Separator();
|
||||
UI7::Label("FTrace:");
|
||||
UI7::Checkbox("Enable Overlay", pdi_ftraced);
|
||||
UI7::Separator();
|
||||
UI7::Label("FTrace Flags:");
|
||||
auto &pd_ft_ovl = pd_ftrace_ovl_flags;
|
||||
OverlayFlag(pd_ft_ovl, PDFTraceOverlayFlags_DisplayName,
|
||||
"Display Func Name");
|
||||
OverlayFlag(pd_ft_ovl, PDFTraceOverlayFlags_DisplayHelp, "Display Help");
|
||||
OverlayFlag(pd_ft_ovl, PDFTraceOverlayFlags_DisplayAverage,
|
||||
"Average Time");
|
||||
OverlayFlag(pd_ft_ovl, PDFTraceOverlayFlags_DisplayMin, "Minimum Time");
|
||||
OverlayFlag(pd_ft_ovl, PDFTraceOverlayFlags_DisplayMax, "Maximum Time");
|
||||
OverlayFlag(pd_ft_ovl, PDFTraceOverlayFlags_FillBg, "Darker Background");
|
||||
UI7::Separator();
|
||||
UI7::Label("Metrik");
|
||||
UI7::Label("Format: Usage | Current Time -> Average");
|
||||
UI7::Checkbox("Enable Overlay", pdi_metrikd);
|
||||
UI7::Checkbox("Bottom Screen", pdi_mt_screen);
|
||||
UI7::ColorSelector("Text", pdi_mt_txtcolor);
|
||||
UI7::ColorSelector("Text Background", pdi_mt_color);
|
||||
UI7::Label("TextSize: " + std::to_string(pdi_mt_txtSize));
|
||||
UI7::SameLine();
|
||||
if (UI7::Button("+")) {
|
||||
pdi_mt_txtSize += 0.1;
|
||||
}
|
||||
UI7::SameLine();
|
||||
if (UI7::Button("-")) {
|
||||
pdi_mt_txtSize -= 0.1;
|
||||
}
|
||||
UI7::Separator();
|
||||
UI7::Label("Metrik Flags:");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_FPS,
|
||||
"Application average");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_CPU, "CPU Usage");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_GPU, "GPU Usage");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_CMD, "Command Buf Usage");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_LMM, "Linear Space Free");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_LVT, "LI Vertices");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_LID, "LI Indices");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_LDM, "LI Draw Commands");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_LDC, "LI Draw Calls");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_PDO, "Display Info Line");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_MTD, "MemTrack Info");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_CGR, "Display CPU Graph");
|
||||
OverlayFlag(pd_ovl_flags, PDMetrikOverlayFlags_GGR, "Display GPU Graph");
|
||||
UI7::EndMenu();
|
||||
}
|
||||
} else if (m_state == RFV) {
|
||||
LI::OnScreen(false);
|
||||
if (UI7::BeginMenu("Palladium -> Font Viewer")) {
|
||||
UI7::SetCursorPos(NVec2(395, 2));
|
||||
UI7::Label(PDVSTRING, PDTextFlags_AlignRight);
|
||||
UI7::RestoreCursor();
|
||||
UI7::Label("Font: " + LI::GetFont()->GetName());
|
||||
UI7::EndMenu();
|
||||
}
|
||||
|
||||
LI::OnScreen(true);
|
||||
if (UI7::BeginMenu("Press B to go back!", NVec2(),
|
||||
UI7MenuFlags_Scrolling)) {
|
||||
UI7::EndMenu();
|
||||
}
|
||||
}
|
||||
// Standart Logic
|
||||
/// Requests
|
||||
for (const auto &it : shared_request) {
|
||||
if (it.first == 0x00000001) {
|
||||
m_state = (RState)it.second;
|
||||
} else if (it.first == 0x00000002) {
|
||||
if (it.second) {
|
||||
std::fstream cfg_wrt(pdi_config_path + "/config.rc7", std::ios::out);
|
||||
pdi_config["metrik-settings"]["show"] = pdi_metrikd;
|
||||
pdi_config["metrik-settings"]["Screen"] = pdi_mt_screen;
|
||||
pdi_config["metrik-settings"]["config"] = pd_ovl_flags;
|
||||
pdi_config["metrik-settings"]["Text"] = pdi_mt_txtcolor;
|
||||
pdi_config["metrik-settings"]["Size"] = pdi_mt_txtSize;
|
||||
pdi_config["metrik-settings"]["Bg"] = pdi_mt_color;
|
||||
cfg_wrt << pdi_config.dump(4);
|
||||
cfg_wrt.close();
|
||||
pdi_settings = false;
|
||||
Hid::Clear();
|
||||
Palladium::Scene::Back();
|
||||
// Instant break logic or it will crash
|
||||
return;
|
||||
}
|
||||
} else if (it.first == 0x00000003) {
|
||||
if (it.second)
|
||||
Palladium::AddOvl(std::make_unique<Ovl_Keyboard>(kbd_test, kbd_state));
|
||||
}
|
||||
}
|
||||
/// Clear if handled
|
||||
shared_request.clear();
|
||||
|
||||
if (statemtold != pdi_metrikd && pdi_metrikd == true)
|
||||
Palladium::AddOvl(std::make_unique<Ovl_Metrik>(
|
||||
&pdi_metrikd, &pdi_mt_screen, &pdi_mt_color, &pdi_mt_txtcolor,
|
||||
&pdi_mt_txtSize));
|
||||
statemtold = pdi_metrikd;
|
||||
if (stateftold != pdi_ftraced && pdi_ftraced == true)
|
||||
Palladium::AddOvl(std::make_unique<Ovl_Ftrace>(&pdi_ftraced));
|
||||
stateftold = pdi_ftraced;
|
||||
|
||||
if (m_state == RSETTINGS) {
|
||||
if (d7_hUp & KEY_B) {
|
||||
std::fstream cfg_wrt(pdi_config_path + "/config.rc7", std::ios::out);
|
||||
pdi_config["metrik-settings"]["show"] = pdi_metrikd;
|
||||
pdi_config["metrik-settings"]["Screen"] = pdi_mt_screen;
|
||||
pdi_config["metrik-settings"]["config"] = pd_ovl_flags;
|
||||
pdi_config["metrik-settings"]["Text"] = pdi_mt_txtcolor;
|
||||
pdi_config["metrik-settings"]["Size"] = pdi_mt_txtSize;
|
||||
pdi_config["metrik-settings"]["Bg"] = pdi_mt_color;
|
||||
cfg_wrt << pdi_config.dump(4);
|
||||
cfg_wrt.close();
|
||||
pdi_settings = false;
|
||||
Hid::Clear();
|
||||
Palladium::Scene::Back();
|
||||
}
|
||||
}
|
||||
if (m_state == RUI7 || m_state == RFV) {
|
||||
if (d7_hUp & KEY_B) {
|
||||
m_state = RSETTINGS;
|
||||
}
|
||||
}
|
||||
if (m_state == ROVERLAYS) {
|
||||
mtovlstate = pdi_metrikd ? "true" : "false";
|
||||
mtscreenstate = pdi_mt_screen ? "Bottom" : "Top";
|
||||
if (d7_hUp & KEY_B) {
|
||||
m_state = RSETTINGS;
|
||||
}
|
||||
}
|
||||
if (m_state == RFTRACE) {
|
||||
if (d7_hDown & KEY_DOWN) {
|
||||
if (ftrace_index < (int)Palladium::Ftrace::pd_traces.size() - 1)
|
||||
ftrace_index++;
|
||||
}
|
||||
if (d7_hDown & KEY_UP) {
|
||||
if (ftrace_index > 0) ftrace_index--;
|
||||
}
|
||||
if (d7_hUp & KEY_B) {
|
||||
m_state = RSETTINGS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Palladium::LoadSettings() {
|
||||
if (!pdi_settings)
|
||||
Palladium::Scene::Load(std::make_unique<Palladium::RSettings>());
|
||||
}
|
||||
|
||||
void Palladium::LoadThemeEditor() {
|
||||
Palladium::Scene::Load(std::make_unique<Palladium::ThemeEditor>());
|
||||
}
|
||||
|
||||
void Palladium::AddOvl(std::unique_ptr<Palladium::Ovl> overlay) {
|
||||
pdi_overlays.push_back(std::move(overlay));
|
||||
}
|
||||
|
||||
void Palladium::FadeOut() {
|
||||
if (!pdi_wait_fade) {
|
||||
pdi_fadein = true;
|
||||
pdi_fadealpha = 0;
|
||||
pdi_wait_fade = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Palladium::FadeIn() {
|
||||
if (!pdi_wait_fade) {
|
||||
pdi_fadeout = true;
|
||||
pdi_fadealpha = 255;
|
||||
pdi_wait_fade = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Palladium::FadeDisplay() { Npifade(); }
|
||||
|
||||
float Palladium::GetTime() { return pdi_time; }
|
||||
|
||||
std::string Palladium::GetAppDirectory() {
|
||||
std::string dir = "sdmc:/Palladium/Apps/" + pdi_app_name;
|
||||
if (!std::filesystem::is_directory(dir))
|
||||
std::filesystem::create_directories(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
std::string Palladium::GetDataDirectory() {
|
||||
std::string dir = GetAppDirectory() + "/data";
|
||||
if (!std::filesystem::is_directory(dir))
|
||||
std::filesystem::create_directories(dir);
|
||||
return dir;
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
#include <pd/thread.hpp>
|
||||
namespace Palladium {
|
||||
Thread::Thread() : m_started(false), m_running(false) { /* do nothing */
|
||||
}
|
||||
|
||||
Thread::Thread(std::function<void(Palladium::Parameter)> t_function,
|
||||
Palladium::Parameter t_parameter, bool t_autostart,
|
||||
bool t_detached, unsigned long long int t_stackSize)
|
||||
: m_started(false), m_running(false) {
|
||||
initialize(t_function, t_parameter, t_autostart, t_detached, t_stackSize);
|
||||
}
|
||||
|
||||
Thread::~Thread() {
|
||||
join();
|
||||
|
||||
if (m_started) threadFree(m_thread);
|
||||
}
|
||||
|
||||
void Thread::initialize(std::function<void(Palladium::Parameter)> t_function,
|
||||
Palladium::Parameter t_parameter, bool t_autostart,
|
||||
bool t_detached, unsigned long long int t_stackSize) {
|
||||
m_stackSize = t_stackSize;
|
||||
m_data.m_parameter = t_parameter;
|
||||
m_data.m_function = t_function;
|
||||
m_data.m_running = &m_running;
|
||||
|
||||
if (t_autostart) {
|
||||
start(t_detached);
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::setStackSize(unsigned long long int t_stackSize) {
|
||||
m_stackSize = t_stackSize;
|
||||
}
|
||||
|
||||
void Thread::start(bool t_detached) {
|
||||
if (!m_running) {
|
||||
m_started = true;
|
||||
m_running = true;
|
||||
s32 prio;
|
||||
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
|
||||
m_thread = threadCreate(threadFunction, &m_data, m_stackSize, prio + 1, -2,
|
||||
t_detached);
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::kill() {
|
||||
threadDetach(m_thread);
|
||||
m_running = false;
|
||||
m_started = false;
|
||||
}
|
||||
|
||||
void Thread::join(long long unsigned int t_timeout) {
|
||||
if (m_running) {
|
||||
threadJoin(m_thread, t_timeout);
|
||||
threadFree(m_thread);
|
||||
m_running = false;
|
||||
m_started = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Thread::isRunning() { return m_running; }
|
||||
|
||||
void Thread::sleep() { svcSleepThread(0); }
|
||||
|
||||
void Thread::sleep(int t_milliseconds) {
|
||||
svcSleepThread(1000000 * t_milliseconds);
|
||||
}
|
||||
|
||||
// private methods
|
||||
void Thread::threadFunction(void *arg) {
|
||||
Palladium::Thread::ThreadData data =
|
||||
*static_cast<Palladium::Thread::ThreadData *>(arg);
|
||||
data.m_function(data.m_parameter);
|
||||
*data.m_running = false;
|
||||
}
|
||||
} // namespace Palladium
|
311
source/tools/result_decoder.cpp
Normal file
311
source/tools/result_decoder.cpp
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef PD_EXTENDED_DEBUG
|
||||
#include <pd/tools/result_decoder.hpp>
|
||||
|
||||
static const std::map<int, std::string> modules = {
|
||||
{0, "common"},
|
||||
{1, "kernel"},
|
||||
{2, "util"},
|
||||
{3, "file server"},
|
||||
{4, "loader server"},
|
||||
{5, "tcb"},
|
||||
{6, "os"},
|
||||
{7, "dbg"},
|
||||
{8, "dmnt"},
|
||||
{9, "pdn"},
|
||||
{10, "gsp"},
|
||||
{11, "i2c"},
|
||||
{12, "gpio"},
|
||||
{13, "dd"},
|
||||
{14, "codec"},
|
||||
{15, "spi"},
|
||||
{16, "pxi"},
|
||||
{17, "fs"},
|
||||
{18, "di"},
|
||||
{19, "hid"},
|
||||
{20, "cam"},
|
||||
{21, "pi"},
|
||||
{22, "pm"},
|
||||
{23, "pm_low"},
|
||||
{24, "fsi"},
|
||||
{25, "srv"},
|
||||
{26, "ndm"},
|
||||
{27, "nwm"},
|
||||
{28, "soc"},
|
||||
{29, "ldr"},
|
||||
{30, "acc"},
|
||||
{31, "romfs"},
|
||||
{32, "am"},
|
||||
{33, "hio"},
|
||||
{34, "updater"},
|
||||
{35, "mic"},
|
||||
{36, "fnd"},
|
||||
{37, "mp"},
|
||||
{38, "mpwl"},
|
||||
{39, "ac"},
|
||||
{40, "http"},
|
||||
{41, "dsp"},
|
||||
{42, "snd"},
|
||||
{43, "dlp"},
|
||||
{44, "hio_low"},
|
||||
{45, "csnd"},
|
||||
{46, "ssl"},
|
||||
{47, "am_low"},
|
||||
{48, "nex"},
|
||||
{49, "friends"},
|
||||
{50, "rdt"},
|
||||
{51, "applet"},
|
||||
{52, "nim"},
|
||||
{53, "ptm"},
|
||||
{54, "midi"},
|
||||
{55, "mc"},
|
||||
{56, "swc"},
|
||||
{57, "fatfs"},
|
||||
{58, "ngc"},
|
||||
{59, "card"},
|
||||
{60, "cardnor"},
|
||||
{61, "sdmc"},
|
||||
{62, "boss"},
|
||||
{63, "dbm"},
|
||||
{64, "config"},
|
||||
{65, "ps"},
|
||||
{66, "cec"},
|
||||
{67, "ir"},
|
||||
{68, "uds"},
|
||||
{69, "pl"},
|
||||
{70, "cup"},
|
||||
{71, "gyroscope"},
|
||||
{72, "mcu"},
|
||||
{73, "ns"},
|
||||
{74, "news"},
|
||||
{75, "ro"},
|
||||
{76, "gd"},
|
||||
{77, "card spi"},
|
||||
{78, "ec"},
|
||||
{79, "web browser"},
|
||||
{80, "test"},
|
||||
{81, "enc"},
|
||||
{82, "pia"},
|
||||
{83, "act"},
|
||||
{84, "vctl"},
|
||||
{85, "olv"},
|
||||
{86, "neia"},
|
||||
{87, "npns"},
|
||||
{90, "avd"},
|
||||
{91, "l2b"},
|
||||
{92, "mvd"},
|
||||
{93, "nfc"},
|
||||
{94, "uart"},
|
||||
{95, "spm"},
|
||||
{96, "qtm"},
|
||||
{97, "nfp"},
|
||||
{254, "application"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> levels = {
|
||||
{0, "Success"}, {1, "Info"}, {25, "Status"},
|
||||
{26, "Temporary"}, {27, "Permanent"}, {28, "Usage"},
|
||||
{29, "Reinitialize"}, {30, "Reset"}, {31, "Fatal"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> summaries = {
|
||||
{0, "Success"},
|
||||
{1, "Nothing happened"},
|
||||
{2, "Would block"},
|
||||
{3, "Out of resource"},
|
||||
{4, "Not found"},
|
||||
{5, "Invalid state"},
|
||||
{6, "Not supported"},
|
||||
{7, "Invalid argument"},
|
||||
{8, "Wrong argument"},
|
||||
{9, "Canceled"},
|
||||
{10, "Status changed"},
|
||||
{11, "Internal"},
|
||||
{63, "Invalid result value"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> desccommon = {
|
||||
{0, "Success"},
|
||||
{1000, "Invalid selection"},
|
||||
{1001, "Too large"},
|
||||
{1002, "Not authorized"},
|
||||
{1003, "Already done"},
|
||||
{1004, "Invalid size"},
|
||||
{1005, "Invalid enum value"},
|
||||
{1006, "Invalid combination"},
|
||||
{1007, "No data"},
|
||||
{1008, "Busy"},
|
||||
{1009, "Misaligned address"},
|
||||
{1010, "Misaligned size"},
|
||||
{1011, "Out of memory"},
|
||||
{1012, "Not implemented"},
|
||||
{1013, "Invalid address"},
|
||||
{1014, "Invalid pointer"},
|
||||
{1015, "Invalid handle"},
|
||||
{1016, "Not initialized"},
|
||||
{1017, "Already initialized"},
|
||||
{1018, "Not found"},
|
||||
{1019, "Cancel requested"},
|
||||
{1020, "Already exists"},
|
||||
{1021, "Out of range"},
|
||||
{1022, "Timeout"},
|
||||
{1023, "Invalid result value"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> desckernel = {
|
||||
{2, "Invalid memory permissions."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descos = {
|
||||
{10, "Not enough memory."},
|
||||
{26, "Session closed by remote."},
|
||||
{47, "Invalid command header."},
|
||||
};
|
||||
|
||||
// Need to Fix The Range based Values
|
||||
static const std::map<int, std::string> descfs = {
|
||||
{101, "Archive not mounted or mount-point not found."},
|
||||
{120, "Title or object not found."},
|
||||
{141, "Gamecard not inserted."},
|
||||
{230, "Invalid open flags or permissions."},
|
||||
{391, "NCCH hash check failed."},
|
||||
{302, "RSA or AES-MAC verification failed."},
|
||||
{395, "RomFS or Savedata hash check failed."},
|
||||
{630, "Command not allowed, or missing permissions."},
|
||||
{702, "Invalid path."},
|
||||
{761, "Incorrect ExeFS read size."},
|
||||
{100, "[Media] not found."},
|
||||
{180, "Exists already."},
|
||||
{200, "Not enough space."},
|
||||
{220, "Invalidated archive."},
|
||||
{230, "Unacceptable or write protected."},
|
||||
{340, "0x01"},
|
||||
{360, "Bad format."},
|
||||
{390, "Verification failure."},
|
||||
{400, "0x01"},
|
||||
{600, "Out of resources."},
|
||||
{630, "Access denied."},
|
||||
{661, "0x01"},
|
||||
{700, "Invalid argument."},
|
||||
{730, "Not initialized."},
|
||||
{750, "Already initialized."},
|
||||
{760, "Not supported."},
|
||||
{780, "0x01"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descsrv = {
|
||||
{5,
|
||||
"Invalid string length (service name length is zero or longer than 8 "
|
||||
"chars)."},
|
||||
{6,
|
||||
"Access to service denied (requested a service the application does "
|
||||
"not have access to)."},
|
||||
{7,
|
||||
"String size does not match contents (service name contains unexpected "
|
||||
"null byte)."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descnwm = {
|
||||
{2,
|
||||
"This error usually indicates the wifi chipset in the console is dying "
|
||||
"or dead."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descam = {
|
||||
{4, "Invalid ticket version."},
|
||||
{32, "Empty CIA."},
|
||||
{37, "Invalid NCCH."},
|
||||
{39, "Invalid title version."},
|
||||
{43, "Database doesn\"t exist, or it failed to open."},
|
||||
{44, "Trying to uninstall system-app."},
|
||||
{106,
|
||||
"Invalid signature/CIA. Usually happens when developer UNITINFO is "
|
||||
"enabled in Luma3DS."},
|
||||
{393, "Invalid database."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> deschttp = {
|
||||
{105, "Request timed out."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descnim = {
|
||||
{1,
|
||||
"Invalid string IPC paramater (non null terminated at its indicated "
|
||||
"length)."},
|
||||
{12,
|
||||
"Invalid country code returned by CFG module reading config save "
|
||||
"0xB0000."},
|
||||
{13,
|
||||
"Zero string length console serial number or '000000000000000' "
|
||||
"returned by CFG's SecureInfoGetSerialNo."},
|
||||
{18,
|
||||
"General data reading error of NIM's .dat files from its system save, "
|
||||
"bad data or bad data lengths."},
|
||||
{22,
|
||||
"General invalid data or length of data returned from nintendo "
|
||||
"servers. (Only applicable for some operations)"},
|
||||
{25,
|
||||
"IntegrityVerificationSeed is waiting on servers to be synced into "
|
||||
"console. Can't processed with online services without sync being "
|
||||
"completed first over IPC request."},
|
||||
{26,
|
||||
"Unavailable/unaccessable IntegrityVerificationSeed on Nintendo "
|
||||
"servers. May happen if NIM is told to import "
|
||||
"IntegrityVerificationSeed from servers at any time other than after "
|
||||
"the successful System Transfer reboot."},
|
||||
{27,
|
||||
"Invalid country language code returned by CFG module reading config "
|
||||
"save 0xA0002."},
|
||||
{37,
|
||||
"Service is in Standby Mode. (eShop ban? General service is down? "
|
||||
"This caused by a server response flag on account information. "
|
||||
"Account is not referring to NNID.)"},
|
||||
{39, "HTTP Status non 200. (Only applicable for some operations)"},
|
||||
{40, "General XML read/write error while processing Auto Delivery XMLs."},
|
||||
{41,
|
||||
"General XML read/write error while processing Auto Delivery XMLs. "
|
||||
"(Stubbed virtual call was called)"},
|
||||
{58,
|
||||
"Invalid NPNS token returned by CFG module reading config save 0xF0006."},
|
||||
{67, "HTTP Status 404 while trying to download a game's seed."},
|
||||
{68, "HTTP Status 503 while trying to download a game's seed."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descmvd = {
|
||||
{271, "Invalid configuration."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descqtm = {
|
||||
{8, "Camera is already in use or busy."},
|
||||
};
|
||||
|
||||
// Need to Fix The Range based Values
|
||||
static const std::map<int, std::string> descapplication = {
|
||||
{0,
|
||||
"The application raised an error. Please consult the application's "
|
||||
"source code or ask the author for assistance with it."},
|
||||
{1024, "0x01"},
|
||||
};
|
||||
#endif
|
85
source/ui7/drawlist.cpp
Normal file
85
source/ui7/drawlist.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/drawlist.hpp>
|
||||
|
||||
namespace PD {
|
||||
void UI7DrawList::AddRectangle(vec2 pos, vec2 szs, const UI7Color& clr) {
|
||||
if (!ren->InBox(pos, szs, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
auto rect = ren->CreateRect(pos, szs, 0.f);
|
||||
auto cmd = LI::Command::New();
|
||||
ren->SetupCommand(cmd);
|
||||
ren->UseTex();
|
||||
cmd->Layer(layer);
|
||||
ren->QuadCommand(cmd, rect, vec4(0.f, 1.f, 1.f, 0.f), clr);
|
||||
commands.push_back(cmd);
|
||||
}
|
||||
|
||||
void UI7DrawList::AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2,
|
||||
const UI7Color& clr) {
|
||||
if (!ren->InBox(pos0, pos1, pos2, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
auto cmd = LI::Command::New();
|
||||
ren->SetupCommand(cmd);
|
||||
ren->UseTex();
|
||||
cmd->Layer(layer);
|
||||
ren->TriangleCommand(cmd, pos0, pos1, pos2, clr);
|
||||
commands.push_back(cmd);
|
||||
}
|
||||
|
||||
void UI7DrawList::AddText(vec2 pos, const std::string& text,
|
||||
const UI7Color& clr, LITextFlags flags = 0,
|
||||
vec2 box = vec2()) {
|
||||
// Dont create a Command here as TextCommand has autosetup
|
||||
// cause it needs to generate multiple commands if
|
||||
// Font uses multiple textures
|
||||
ren->TextCommand(commands, pos, clr, text, flags, box);
|
||||
}
|
||||
|
||||
void UI7DrawList::AddImage(vec2 pos, Texture::Ref img) {
|
||||
if (!ren->InBox(pos, img->GetSize(), ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
auto rect = ren->CreateRect(pos, img->GetSize(), 0.f);
|
||||
auto cmd = LI::Command::New();
|
||||
ren->SetupCommand(cmd);
|
||||
ren->UseTex(img);
|
||||
cmd->Layer(layer);
|
||||
ren->QuadCommand(cmd, rect, vec4(0.f, 1.f, 1.f, 0.f), 0xffffffff);
|
||||
commands.push_back(cmd);
|
||||
}
|
||||
|
||||
void UI7DrawList::Clear() { commands.clear(); }
|
||||
|
||||
void UI7DrawList::Process() {
|
||||
// UI7 Commands Use LI7 as default feature
|
||||
ren->OptiCommandList(commands);
|
||||
for (auto command : commands) {
|
||||
ren->PushCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace PD
|
Reference in New Issue
Block a user