Get it finally working (somehow)

- Add working example
- Add Namespace defs for Iron Ctr and C3D
- Add Exit func / Vertex / Index counter to Iron
- Add format bytes function to utils
- Make stb_image optional
- Compute texture uv's
- Clear Everything in Drawlist::Clear
- Use Amy::mat4 as matrix lib
- Fix the most stupid rendering bug (i -> m_idx)
This commit is contained in:
2025-12-01 22:10:18 +01:00
parent 078af99ae5
commit 777b23f4c8
15 changed files with 138 additions and 376 deletions

View File

@@ -5,8 +5,9 @@ project(amethyst)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED true) set(CMAKE_CXX_STANDARD_REQUIRED true)
option(AMY_BUILD_3DS "Build for 3ds" ON)
option(AMY_GOD_DEV "Turn this on if you think you are god" OFF) option(AMY_GOD_DEV "Turn this on if you think you are god" OFF)
# THis option should be disabled if you use STB_IMAGE in you main project
set(AMY_BUILD_STB_IMAGE "Include STB Image code" CACHE BOOL 1)
#add_subdirectory(vendor/libpicasso) #add_subdirectory(vendor/libpicasso)
@@ -26,10 +27,8 @@ add_library(${PROJECT_NAME} STATIC
) )
target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PUBLIC include)
#target_link_libraries(${PROJECT_NAME} PUBLIC pica::pica) #target_link_libraries(${PROJECT_NAME} PUBLIC pica::pica)
if(${AMY_BUILD_3DS})
target_link_libraries(${PROJECT_NAME} PUBLIC m z ctru citro3d) target_link_libraries(${PROJECT_NAME} PUBLIC m z ctru citro3d)
target_compile_definitions(${PROJECT_NAME} PUBLIC AMY_3DS) target_compile_definitions(${PROJECT_NAME} PUBLIC AMY_3DS AMY_STB_IMAGE=${AMY_BUILD_STB_IMAGE})
endif()
add_subdirectory(example) add_subdirectory(example)

View File

@@ -1,25 +1,57 @@
#include <amethyst.hpp> #include <amethyst.hpp>
#include <iostream>
class Example : public Amy::App { class Example : public Amy::App {
public: public:
Example() { Example() {
Amy::Ctr::Init(); Amy::Ctr::Init();
consoleInit(GFX_BOTTOM, NULL);
Amy::C3D::Init(); Amy::C3D::Init();
Top = Amy::C3D::CreateScreen(GFX_TOP); Top = Amy::C3D::CreateScreen(GFX_TOP);
Mgr = new Amy::AssetMgr();
Mgr->AutoLoad("icon", "romfs:/icon.png");
Amy::Iron::Init();
dl = new Amy::Iron::Drawlist();
}
~Example() {
delete Top;
delete dl;
delete Mgr;
Amy::C3D::Deinit();
} }
~Example() { delete Top; }
void Main() { void Main() {
std::cout << std::format("\x1b[1;1HDelta: {:.3f} -> {:.3} FPS\x1b[K",
this->Delta(), 1000.0 / this->Delta());
std::cout << std::format("\x1b[2;1HTime: {:.3f}\x1b[K", this->Time());
std::cout << std::format(
"\x1b[3;1H\nLin: {}\nVertices: {}\nIndices: "
"{}\x1b[K",
Amy::Utils::FormatBytes(linearSpaceFree()), Amy::Iron::VerticesDrawn(),
Amy::Iron::IndicesDrawn());
Amy::C3D::StartFrame(); Amy::C3D::StartFrame();
Top->Clear(); Top->Clear();
Top->Use(); Top->Use();
dl->DrawTex(Mgr->Get<Amy::Texture>("icon"));
dl->DrawRectFilled(Amy::fvec2(50, 0), 48, 0x99999999);
dl->DrawCircleFilled(Amy::fvec2(200, 120), 50, 0xffffffff, 40);
dl->DrawSolid();
dl->DrawRectFilled(0, 50, 0x4400ff00);
Amy::Iron::NewFrame();
Amy::Iron::DrawOn(Top);
Amy::Iron::Draw(*dl);
dl->Clear();
Amy::C3D::EndFrame(); Amy::C3D::EndFrame();
} }
Amy::C3D::Screen* Top; Amy::C3D::Screen* Top;
Amy::AssetMgr* Mgr;
Amy::Iron::Drawlist* dl;
}; };
int main() { int main() {
Amy::RegisterCxxExceptionHandler();
Example App; Example App;
App.Run(); App.Run();
return 0; return 0;

View File

@@ -1,118 +0,0 @@
#include <amethyst.hpp>
#include <cstdlib>
#include <iostream>
#include <map>
#include "amethyst/iron.hpp"
struct memory_metrics {
uint64_t t_TotalAllocated = 0; ///< Total Allocated Memory
uint64_t t_TotalFreed = 0; ///< Total Deleted Memory
/// @brief Gets the Currently Allocated Memory
uint32_t t_CurrentlyAllocated() { return t_TotalAllocated - t_TotalFreed; }
};
static memory_metrics metrics;
bool rd7i_enable_memtrack = true;
void* operator new(size_t size) {
void* ptr = malloc(size);
if (rd7i_enable_memtrack) metrics.t_TotalAllocated += size;
return ptr;
}
void operator delete(void* memory, size_t size) {
if (rd7i_enable_memtrack) metrics.t_TotalFreed += size;
free(memory);
}
size_t GetTotalAllocated() { return metrics.t_TotalAllocated; }
size_t GetTotalFreed() { return metrics.t_TotalFreed; }
size_t GetCurrent() { return metrics.t_CurrentlyAllocated(); }
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) {
i++;
b /= 1024;
}
if (i >= (int)endings.size()) {
i = (int)endings.size() - 1;
}
return std::format("{:.1f} {}", b, endings[i]);
}
class example : public Amy::App {
public:
example() {
Amy::Ctr::Init();
consoleInit(GFX_BOTTOM, NULL);
Amy::C3D::Init();
m_top = Amy::C3D::CreateScreen(GFX_TOP);
Amy::Iron::Init();
dl = new Amy::Iron::Drawlist();
dl->DrawSolid();
mgr.AutoLoad("shader", "romfs:/shaders/shader2d.shbin");
mgr.Get<Amy::C3D::Shader>("shader")->Input(GPU_FLOAT, 3);
mgr.Get<Amy::C3D::Shader>("shader")->Input(GPU_FLOAT, 3);
mgr.AutoLoad("icon", "romfs:/icon.png");
};
~example() {
Amy::C3D::DeleteScreen(m_top);
Amy::C3D::Deinit();
};
void Main() override {
std::cout << std::format("\x1b[1;1HDelta: {:.3f} -> {:.3} FPS\x1b[K", this->Delta(), 1000.0/this->Delta());
std::cout << std::format("\x1b[2;1HTime: {:.3f}\x1b[K", this->Time());
std::cout << std::format(
"\x1b[3;1HMem: {}\n +{}\n -{}\nLin: {}\x1b[K",
FormatBytes(GetCurrent()), FormatBytes(GetTotalAllocated()),
FormatBytes(GetTotalFreed()), FormatBytes(linearSpaceFree()));
Amy::C3D::StartFrame();
m_top->Use();
m_top->Clear();
dl->DrawTex(mgr.Get<Amy::Texture>("icon"));
dl->DrawRectFilled(100, 48, 0xffffffff);
dl->DrawSolid();
dl->DrawRectFilled(0, 50, 0xffffffff);
Amy::Iron::NewFrame();
Amy::Iron::DrawOn(m_top);
Amy::Iron::Draw(*dl);
dl->Clear();
/*mgr.Get<Amy::C3D::Shader>("shader")->Use();
mgr.Get<Amy::C3D::Shader>("shader")->SetMat4(0, mtx);
C3D_ImmDrawBegin(GPU_TRIANGLES);
C3D_ImmSendAttrib(200, 50, 0, 0);
C3D_ImmSendAttrib(1, 0, 0, 1);
C3D_ImmSendAttrib(300, 190, 0, 0);
C3D_ImmSendAttrib(0, 1, 0, 1);
C3D_ImmSendAttrib(100, 190, 0, 0);
C3D_ImmSendAttrib(0, 0, 1, 1);
C3D_ImmDrawEnd();*/
Amy::C3D::EndFrame();
}
private:
Amy::C3D::Screen* m_top = nullptr;
Amy::Iron::Drawlist* dl = nullptr;
Amy::C3D::Shader* test = nullptr;
Amy::AssetMgr mgr;
Amy::mat4 mtx =
Amy::mat4::identity() * Amy::mat4::ortho(0, 400, 240, 0, 0, 1);
};
int main() {
Amy::RegisterCxxExceptionHandler();
example app;
app.Run();
return 0;
}

View File

@@ -1,91 +0,0 @@
#include <3ds.h>
#include <citro3d.h>
#include <string.h>
#include <amethyst.hpp>
struct vertex {
vertex(Amy::fvec2 p, Amy::fvec2 tc, Amy::ui c) {
pos = pos;
uv = tc;
color = c;
}
vertex() = default;
Amy::fvec2 pos;
Amy::fvec2 uv;
Amy::ui color;
};
std::vector<vertex, Amy::LinearAllocator<vertex>> vbuf;
static int uLoc_projection = 0;
static Amy::C3D::Shader* Shader = nullptr;
static Amy::AssetMgr Assets;
static void sceneInit(void) {
Shader = new Amy::C3D::Shader("romfs:/shaders/li2.shbin");
uLoc_projection = Shader->loc("projection");
Shader->Input(GPU_FLOAT, 2);
Shader->Input(GPU_FLOAT, 2);
Shader->Input(GPU_UNSIGNED_BYTE, 4);
vbuf.resize(6);
vbuf[0] = vertex(Amy::fvec2(300, 40), Amy::fvec2(1, 1), 0xffffffff);
vbuf[1] = vertex(Amy::fvec2(100, 40), Amy::fvec2(0, 1), 0xffffffff);
vbuf[2] = vertex(Amy::fvec2(100, 200), Amy::fvec2(0, 0), 0xffffffff);
vbuf[3] = vertex(Amy::fvec2(100, 200), Amy::fvec2(0, 0), 0xffffffff);
vbuf[4] = vertex(Amy::fvec2(300, 200), Amy::fvec2(1, 0), 0xffffffff);
vbuf[5] = vertex(Amy::fvec2(300, 40), Amy::fvec2(1, 1), 0xffffffff);
Amy::C3D::BufCfg<3>(vbuf.data(), sizeof(vertex));
Amy::C3D::Frag::Edit();
Amy::C3D::Frag::Src(C3D_Both, GPU_TEXTURE0);
Amy::C3D::Frag::Func(C3D_Both, GPU_MODULATE);
Assets.AutoLoad("white", "romfs:/white.png");
}
static void sceneRender(void) {
Amy::C3D::DepthTest(false);
Shader->Use();
Shader->SetMat4(uLoc_projection, Amy::mat4::ortho(0, 400, 240, 0, 1, -1));
Assets.Get<Amy::Texture>("white")->Bind();
Amy::C3D::DrawArrays(0, vbuf.size());
Amy::C3D::DepthTest(true);
}
static void sceneExit(void) {
vbuf.clear();
delete Shader;
}
int main() {
Amy::RegisterCxxExceptionHandler();
Amy::Ctr::Init();
Amy::C3D::Init();
auto Top = Amy::C3D::CreateScreen(GFX_TOP);
sceneInit();
while (aptMainLoop()) {
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break;
Amy::C3D::StartFrame();
Top->Clear();
Top->Use();
sceneRender();
Amy::C3D::EndFrame();
}
// Deinitialize the scene
sceneExit();
Amy::C3D::Deinit();
gfxExit();
romfsExit();
return 0;
}

View File

@@ -1,89 +0,0 @@
#include <amethyst.hpp>
typedef struct {
float pos[3];
float color[4];
} Vertex;
static const Vertex vertex_list[] = {
{{200.0f, 200.0f, 0.5f}, {1.0f, 0.0f, 0.0f, 1.0f}},
{{100.0f, 40.0f, 0.5f}, {0.0f, 1.0f, 0.0f, 1.0f}},
{{300.0f, 40.0f, 0.5f}, {0.0f, 0.0f, 1.0f, 1.0f}},
};
#define vertex_list_count (sizeof(vertex_list) / sizeof(vertex_list[0]))
static int uLoc_projection;
Amy::AssetMgr* Assets = nullptr;
static void* vbo_data;
extern "C" {
static void sceneInit(void) {
Assets->AutoLoad("shader", "romfs:/shaders/shader2d.shbin");
Assets->Get<Amy::C3D::Shader>("shader")->Input(GPU_FLOAT, 3);
Assets->Get<Amy::C3D::Shader>("shader")->Input(GPU_FLOAT, 4);
uLoc_projection = Assets->Get<Amy::C3D::Shader>("shader")->loc("projecttion");
vbo_data = linearAlloc(sizeof(vertex_list));
memcpy(vbo_data, vertex_list, sizeof(vertex_list));
// Configure buffers
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
BufInfo_Add(bufInfo, vbo_data, sizeof(Vertex), 2, 0x10);
// Configure the first fragment shading substage to just pass through the
// vertex color See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml
// for more insight
C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env);
C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR);
C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
}
}
static void sceneRender(void) {
Assets->Get<Amy::C3D::Shader>("shader")->Use();
Assets->Get<Amy::C3D::Shader>("shader")->SetMat4(
uLoc_projection, Amy::mat4::ortho(0, 400, 240, 0, 1, -1));
Amy::C3D::DrawArrays(0, vertex_list_count);
}
static void sceneExit(void) {
// Free the VBO
linearFree(vbo_data);
Assets->Remove("shader");
}
int main() {
Amy::RegisterCxxExceptionHandler();
Amy::Ctr::Init();
Amy::C3D::Init();
auto Top = Amy::C3D::CreateScreen(GFX_TOP);
Assets = new Amy::AssetMgr();
sceneInit();
while (aptMainLoop()) {
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break;
Amy::C3D::StartFrame();
Top->Clear();
Top->Use();
sceneRender();
Amy::C3D::EndFrame();
}
sceneExit();
C3D_Fini();
gfxExit();
romfsExit();
return 0;
}

View File

@@ -12,3 +12,7 @@
namespace Amy { namespace Amy {
void RegisterCxxExceptionHandler(); void RegisterCxxExceptionHandler();
} }
using Iron = Amy::Iron;
namespace Ctr = Amy::Ctr;
using C3D = Amy::C3D;

View File

@@ -48,9 +48,9 @@ class Iron {
std::vector<u16> IndexBuf; std::vector<u16> IndexBuf;
ivec4 ScissorRect; ivec4 ScissorRect;
bool ScissorOn = false; bool ScissorOn = false;
int Layer; int Layer = 0;
int Index; int Index = 0;
Texture* Tex; Texture* Tex = nullptr;
}; };
class Drawlist { class Drawlist {
public: public:
@@ -131,6 +131,7 @@ class Iron {
~Iron() = default; ~Iron() = default;
static void Init(); static void Init();
static void Exit();
static void NewFrame(); static void NewFrame();
static void DrawOn(C3D::Screen* screen); static void DrawOn(C3D::Screen* screen);
static void Draw(const std::vector<Command::ref>& data); static void Draw(const std::vector<Command::ref>& data);
@@ -152,6 +153,9 @@ class Iron {
static bool InBox(const fvec2& a, const fvec2& b, const fvec2& c, static bool InBox(const fvec2& a, const fvec2& b, const fvec2& c,
const fvec4& area); const fvec4& area);
static ui VerticesDrawn() { return VertexCount; }
static ui IndicesDrawn() { return IndexCount; }
private: private:
static void pSetupShader(); static void pSetupShader();
static void pFragConfig(); static void pFragConfig();
@@ -165,5 +169,7 @@ class Iron {
static mat4 m_mtx; static mat4 m_mtx;
static int m_idx, m_vtx; static int m_idx, m_vtx;
static Texture* m_solid; static Texture* m_solid;
static ui VertexCount;
static ui IndexCount;
}; };
} // namespace Amy } // namespace Amy

View File

@@ -20,7 +20,7 @@ class LinearAllocator {
T* allocate(std::size_t n) { T* allocate(std::size_t n) {
if (n > max_size()) { if (n > max_size()) {
throw std::bad_alloc(); throw std::runtime_error("[Amy] LinearAllocator: Bad alloc!");
} }
return static_cast<T*>(linearAlloc(n * sizeof(T))); return static_cast<T*>(linearAlloc(n * sizeof(T)));
} }

View File

@@ -5,6 +5,7 @@
#include <chrono> #include <chrono>
#include <cinttypes> #include <cinttypes>
#include <functional> #include <functional>
#include <format>
#include <map> #include <map>
#include <memory> #include <memory>
#include <numbers> #include <numbers>

View File

@@ -9,6 +9,7 @@ class Error : public std::runtime_error {
}; };
namespace Utils { namespace Utils {
vec<uc> LoadFile2Mem(ksr path); vec<uc> LoadFile2Mem(ksr path);
str FormatBytes(ull bytes);
ui HashMemory(kvr<uc> data); ui HashMemory(kvr<uc> data);
ui NextPow2(ui v); ui NextPow2(ui v);
bool IsSingleBitNum(ui v); bool IsSingleBitNum(ui v);

View File

@@ -2,7 +2,11 @@
#include <amethyst/utils.hpp> #include <amethyst/utils.hpp>
#include <stdexcept> #include <stdexcept>
// Only include stb Code if we need it
// Otherwise we just build the header
#if AMY_STB_IMAGE == 1
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#endif
#include <stb_image.h> #include <stb_image.h>
namespace Amy { namespace Amy {

View File

@@ -23,14 +23,22 @@ void Iron::Drawlist::Merge(Iron::Drawlist *list) {
list->Clear(); list->Clear();
} }
void Iron::Drawlist::Clear() { pData.clear(); } void Iron::Drawlist::Clear() {
pData.clear();
pPath.clear();
DrawSolid();
while (!ClipRects.empty()) {
ClipRects.pop();
}
pLayer = 0;
}
Iron::Command::ref Iron::Drawlist::NewCommand() { Iron::Command::ref Iron::Drawlist::NewCommand() {
auto ret = std::make_unique<Command>(); auto ret = std::make_unique<Command>();
ret->Layer = pLayer; ret->Layer = pLayer;
ret->Index = pData.size(); ret->Index = pData.size();
ret->Tex = pTex; ret->Tex = pTex;
return ret; return std::move(ret);
} }
void Iron::Drawlist::clipCmd(Command* ptr) { void Iron::Drawlist::clipCmd(Command* ptr) {

View File

@@ -3,18 +3,6 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#define catch2() \
; \
({ \
std::cout << std::format("{}:{}", __FILE__, __LINE__) << std::endl; \
while (aptMainLoop()) { \
hidScanInput(); \
if (hidKeysDown() & KEY_A) { \
break; \
} \
} \
})
namespace Amy { namespace Amy {
const char* __ironshader__ = R"(; LI7 Shader const char* __ironshader__ = R"(; LI7 Shader
; Constants ; Constants
@@ -64,7 +52,8 @@ C3D::Shader* Iron::m_shader = nullptr;
mat4 Iron::m_mtx; mat4 Iron::m_mtx;
int Iron::m_idx = 0, Iron::m_vtx = 0; int Iron::m_idx = 0, Iron::m_vtx = 0;
Texture* Iron::m_solid = nullptr; Texture* Iron::m_solid = nullptr;
C3D_Mtx __m; ui Iron::VertexCount = 0;
ui Iron::IndexCount = 0;
void Iron::Init() { void Iron::Init() {
pSetupShader(); pSetupShader();
@@ -73,20 +62,25 @@ void Iron::Init() {
pInitSolidTex(); pInitSolidTex();
} }
void Iron::Exit() {
delete m_solid;
delete m_shader;
m_vbuf.clear();
m_ibuf.clear();
}
void Iron::NewFrame() { void Iron::NewFrame() {
VertexCount = m_vtx;
IndexCount = m_idx;
m_idx = 0; m_idx = 0;
m_vtx = 0; m_vtx = 0;
} }
void Iron::DrawOn(C3D::Screen* screen) { void Iron::DrawOn(C3D::Screen* screen) {
m_shader->Use(); m_shader->Use();
Mtx_Identity(&__m); m_mtx = mat4::ortho(0.f, (float)screen->Width(), (float)screen->Height(), 0.f,
Mtx_OrthoTilt(&__m, 0, (float)screen->Width(), (float)screen->Height(), 0.f, 1.f, -1.f);
1.f, -1.f, true); m_shader->SetMat4(uLocProj, m_mtx);
// m_mtx = mat4::ortho(0.f, (float)screen->Width(), (float)screen->Height(),
// 0.f,
// 1.f, -1.f);
m_shader->SetMat4(uLocProj, &__m);
} }
void Iron::Draw(const std::vector<Iron::Command::ref>& data) { void Iron::Draw(const std::vector<Iron::Command::ref>& data) {
@@ -102,7 +96,7 @@ void Iron::Draw(const std::vector<Iron::Command::ref>& data) {
} }
auto scissorOn = data[i]->ScissorOn; auto scissorOn = data[i]->ScissorOn;
auto scissor = data[i]->ScissorRect; auto scissor = data[i]->ScissorRect;
auto start = i; auto start = m_idx;
// Loop until a statgechange and copy all data into Vertex/index buf // Loop until a statgechange and copy all data into Vertex/index buf
while (i < data.size() && scissorOn == data[i]->ScissorOn && while (i < data.size() && scissorOn == data[i]->ScissorOn &&
@@ -119,7 +113,7 @@ void Iron::Draw(const std::vector<Iron::Command::ref>& data) {
m_ibuf[m_idx++] = m_vtx + c->IndexBuf[j]; m_ibuf[m_idx++] = m_vtx + c->IndexBuf[j];
} }
for (int j = 0; j < c->VertexBuf.size(); j++) { for (int j = 0; j < c->VertexBuf.size(); j++) {
m_vbuf[m_vtx++] = c->VertexBuf[j]; m_vbuf[m_vtx++] = std::move(c->VertexBuf[j]);
} }
i++; i++;
} }
@@ -127,17 +121,9 @@ void Iron::Draw(const std::vector<Iron::Command::ref>& data) {
///// SCISSOR LOGIC END ///// ///// SCISSOR LOGIC END /////
tex->Bind(); tex->Bind();
C3D::BufCfg<3>(m_vbuf.data(), sizeof(Vertex)); C3D::BufCfg<3>(m_vbuf.data(), sizeof(Vertex));
C3D::DrawElements(i - start, m_ibuf.data() + start); C3D::DrawElements(m_idx - start, m_ibuf.data() + start);
} }
C3D::DepthTest(true); C3D::DepthTest(true);
/*std::ofstream off("hello.txt");
for (int i = 0; i < m_idx; i++) {
auto& v = m_vbuf[m_ibuf[i]];
off << std::format("{} -> [{}] [{}] #{:08X}\n", m_ibuf[i], v.pos, v.uv,
v.color);
}
off.close();
throw std::runtime_error("halt");*/
} }
bool Iron::pCheckSize(size_t idx, size_t vtx) { bool Iron::pCheckSize(size_t idx, size_t vtx) {
@@ -153,12 +139,13 @@ void Iron::pSetupShader() {
AttrInfo_AddLoader(&m_shader->pInfo, 0, GPU_FLOAT, 2); AttrInfo_AddLoader(&m_shader->pInfo, 0, GPU_FLOAT, 2);
AttrInfo_AddLoader(&m_shader->pInfo, 1, GPU_FLOAT, 2); AttrInfo_AddLoader(&m_shader->pInfo, 1, GPU_FLOAT, 2);
AttrInfo_AddLoader(&m_shader->pInfo, 2, GPU_UNSIGNED_BYTE, 4); AttrInfo_AddLoader(&m_shader->pInfo, 2, GPU_UNSIGNED_BYTE, 4);
// TODO: FUNKTIONIRT NICHT AHHHHHHHHHH
/*m_shader->Load("romfs:/shaders/lithium.shbin"); /*m_shader->Load("romfs:/shaders/lithium.shbin");
// m_shader->Compile(__ironshader__); // m_shader->Compile(__ironshader__);
m_shader->Input(GPU_FLOAT, 2); // pos m_shader->Input(GPU_FLOAT, 2); // pos
m_shader->Input(GPU_FLOAT, 2); // uv m_shader->Input(GPU_FLOAT, 2); // uv
m_shader->Input(GPU_UNSIGNED_BYTE, 4); // color*/ m_shader->Input(GPU_UNSIGNED_BYTE, 4); // color
uLocProj = m_shader->loc("projection"); uLocProj = m_shader->loc("projection");*/
} }
void Iron::pFragConfig() { void Iron::pFragConfig() {

View File

@@ -66,6 +66,8 @@ void Texture::Load(kvr<uc> pixels, int w, int h, int bpp, Image::Format fmt) {
if (!Utils::IsSingleBitNum(pSize.y)) { if (!Utils::IsSingleBitNum(pSize.y)) {
pSize.y = Utils::NextPow2(pSize.y); pSize.y = Utils::NextPow2(pSize.y);
} }
pUv = Amy::fvec4(0, 1.f, (float)w / (float)pSize.x,
1.f - ((float)h / (float)pSize.y));
auto filter = GPU_NEAREST; auto filter = GPU_NEAREST;
auto Format = image2TexFmt(fmt); auto Format = image2TexFmt(fmt);
pTex = new C3D_Tex; pTex = new C3D_Tex;

View File

@@ -17,6 +17,22 @@ vec<uc> LoadFile2Mem(ksr path) {
return res; return res;
} }
str FormatBytes(ull bytes) {
static const vec<str> endings = {
"B", "KB", "MB", "GB", "TB", "Unk",
};
int i = 0;
double b = bytes;
while (b > 1024) {
i++;
b /= 1024;
}
if (i >= (int)endings.size()) {
i = (int)endings.size() - 1;
}
return std::format("{:.1f} {}", b, endings[i]);
}
ui HashMemory(kvr<uc> data) { ui HashMemory(kvr<uc> data) {
ui hash = 4477; ui hash = 4477;
for (auto& it : data) { for (auto& it : data) {