diff --git a/include/Dolphin/os/OSFastCast.h b/include/Dolphin/os/OSFastCast.h new file mode 100644 index 00000000..effad6c8 --- /dev/null +++ b/include/Dolphin/os/OSFastCast.h @@ -0,0 +1,13 @@ +#ifndef _OSFASTCAST_H_ +#define _OSFASTCAST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define OS_FASTCAST_U8 2 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/Kyoto/Basics/CCast.hpp b/include/Kyoto/Basics/CCast.hpp new file mode 100644 index 00000000..565e4b83 --- /dev/null +++ b/include/Kyoto/Basics/CCast.hpp @@ -0,0 +1,29 @@ +#ifndef __CCAST_HPP__ +#define __CCAST_HPP__ + +#include "types.h" +#include "Dolphin/os/OSFastCast.h" + +namespace CCast { +inline u8 ToUint8(register f32 in) { + u8 a; + register u8* ptr = &a; + register u8 r; + + asm { + psq_st in, 0(ptr), 1, OS_FASTCAST_U8 + lbz r, 0(ptr) + } + return r; +} + +inline f32 ToReal32(register const u8& in) { + register f32 r; + asm { + psq_l r, 0(in), 1, 2 + } + return r; +} +} // namespace CCast + +#endif diff --git a/include/Kyoto/Graphics/CColor.hpp b/include/Kyoto/Graphics/CColor.hpp index 0c86ba76..e67df6e4 100644 --- a/include/Kyoto/Graphics/CColor.hpp +++ b/include/Kyoto/Graphics/CColor.hpp @@ -3,12 +3,40 @@ #include "types.h" +#include "Kyoto/Basics/CCast.hpp" + #pragma cpp_extensions on +class CInputStream; class CColor { public: + CColor() {} CColor(u32 col) : mRgba(col) {} - CColor(f32 r, f32 g, f32 b, f32 a = 1.f) : mR(r * 255.f), mG(g * 255.f), mB(b * 255.f), mA(a * 255.f) {} + CColor(CInputStream& in); + CColor(f32 r, f32 g, f32 b, f32 a = 1.f); + CColor(u8 r, u8 g, u8 b, u8 a = 255) { + mR = r; + mG = g; + mB = b; + mA = a; + } + + void Set(float r, float g, float b, float a); + void Get(float& r, float& g, float& b, float& a) const; + void Get(float& r, float& g, float& b) const; + static CColor Lerp(const CColor& a, const CColor& b, float t); + static u32 Lerp(u32 a, u32 b, float t); + static CColor Modulate(const CColor& a, const CColor& b); + static CColor Add(const CColor& a, const CColor& b); + f32 GetRed() const { return CCast::ToReal32(mR) * (1/255.f); } + f32 GetGreen() const { return CCast::ToReal32(mG) * (1/255.f); } + f32 GetBlue() const { return CCast::ToReal32(mB) * (1/255.f); } + f32 GetAlpha() const { return CCast::ToReal32(mA) * (1/255.f); } + u8 GetRedu8() const { return mR; } + u8 GetGreenu8() const { return mG; } + u8 GetBlueu8() const { return mB; } + u8 GetAlphau8() const { return mA; } + u16 ToRGB5A3() const; static const CColor& Black(); static const CColor& White(); diff --git a/include/rstl/algorithm.hpp b/include/rstl/algorithm.hpp new file mode 100644 index 00000000..67bcfd70 --- /dev/null +++ b/include/rstl/algorithm.hpp @@ -0,0 +1,15 @@ +#ifndef _RSTL_MATH_HPP +#define _RSTL_MATH_HPP + +namespace rstl { +template +inline const T& min_val(const T& a, const T& b) { + return (b < a) ? b : a; +} + +template +inline const T& max_val(const T& a, const T& b) { + return (a < b) ? b : a; +} +} +#endif // _RSTL_MATH_HPP diff --git a/src/Kyoto/Graphics/DolphinCColor.cpp b/src/Kyoto/Graphics/DolphinCColor.cpp new file mode 100644 index 00000000..35b7141f --- /dev/null +++ b/src/Kyoto/Graphics/DolphinCColor.cpp @@ -0,0 +1,81 @@ +#include "Kyoto/Graphics/CColor.hpp" + +#include "Kyoto/Streams/CInputStream.hpp" + +#include "rstl/algorithm.hpp" + +CColor::CColor(CInputStream& in) { + float r = in.ReadFloat(); + float g = in.ReadFloat(); + float b = in.ReadFloat(); + Set(r, g, b, in.ReadFloat()); +} + +CColor::CColor(float r, float g, float b, float a) { + mR = r * 255.f; + mG = g * 255.f; + mB = b * 255.f; + mA = a * 255.f; +} + +void CColor::Set(float r, float g, float b, float a) { + mR = CCast::ToUint8(r * 255.f); + mG = CCast::ToUint8(g * 255.f); + mB = CCast::ToUint8(b * 255.f); + mA = CCast::ToUint8(a * 255.f); +} + +void CColor::Get(float& r, float& g, float& b, float& a) const { + r = CCast::ToReal32(mR) * (1 / 255.f); + g = CCast::ToReal32(mG) * (1 / 255.f); + b = CCast::ToReal32(mB) * (1 / 255.f); + a = CCast::ToReal32(mA) * (1 / 255.f); +} + +void CColor::Get(float& r, float& g, float& b) const { + r = CCast::ToReal32(mR) * (1 / 255.f); + g = CCast::ToReal32(mG) * (1 / 255.f); + b = CCast::ToReal32(mB) * (1 / 255.f); +} + +CColor CColor::Lerp(const CColor& a, const CColor& b, float t) { + const float omt = 1.f - t; + return CColor(omt * a.GetRed() + t * b.GetRed(), omt * a.GetGreen() + t * b.GetGreen(), omt * a.GetBlue() + t * b.GetBlue(), + omt * a.GetAlpha() + t * b.GetAlpha()); +} + +/* non-matching https://decomp.me/scratch/WGIlL */ +u32 CColor::Lerp(u32 a, u32 b, float t) { + u32 t256 = t * 256.f; + u32 uVar3 = a & 0x00FF00FF; + u32 uVar4 = b & 0x00FF00FF; + u32 uVar1 = (a >> 8) & 0x00FF00FF; + u32 uVar2 = (b >> 8) & 0x00FF00FF; + u32 new_var = (t256 * (uVar2 - uVar1)) >> 8; + u32 new_var2 = (t256 * (uVar4 - uVar3)) >> 8; + return ((new_var2 + uVar3) & 0x00FF00FF) | (((new_var + uVar1) * 256) & 0xFF00FF00); +} + +CColor CColor::Modulate(const CColor& a, const CColor& b) { + return CColor((u8)((a.GetRedu8() * b.GetRedu8()) / (u8)255), (a.GetGreenu8() * b.GetGreenu8()) / (u8)255, + (a.GetBlueu8() * b.GetBlueu8()) / (u8)255, (a.GetAlphau8() * b.GetAlphau8()) / (u8)255); +} + +CColor CColor::Add(const CColor& arg0, const CColor& arg1) { + return CColor((u8)rstl::min_val< u32 >(255, arg0.GetRedu8() + arg1.GetRedu8()), + (u8)rstl::min_val< u32 >(255, arg0.GetGreenu8() + arg1.GetGreenu8()), + (u8)rstl::min_val< u32 >(255, arg0.GetBlueu8() + arg1.GetBlueu8()), + (u8)rstl::min_val< u32 >(255, arg0.GetAlphau8() + arg1.GetAlphau8())); +} + +u16 CColor::ToRGB5A3() const { + u8 r = GetRedu8(); + u8 g = GetGreenu8(); + u8 b = GetBlueu8(); + u8 a = GetAlphau8(); + u16 ret = (1 << 15) | ((b & 0xf8) >> 3) | ((g & 0xf8) << 2) | ((r & 0xf8) << 7); + if (a != 0xFF) { + ret = ((a & 0xe0) << 7) | ((b & 0xf0) >> 4) | (g & 0xf0) | ((r & 0xf0) << 4); + } + return ret; +}