mirror of
https://github.com/LNH-team/pico-launcher.git
synced 2025-12-05 13:16:06 +01:00
220 lines
6.9 KiB
C++
220 lines
6.9 KiB
C++
#pragma once
|
|
#include "common.h"
|
|
#include "core/math/Point.h"
|
|
#include <libtwl/gfx/gfxOam.h>
|
|
|
|
/// @brief Helper class for building oams.
|
|
class OamBuilder
|
|
{
|
|
u16 _attr0;
|
|
u16 _attr1;
|
|
u16 _attr2;
|
|
|
|
OamBuilder()
|
|
: _attr0(0), _attr1(0), _attr2(0) { }
|
|
|
|
public:
|
|
template <int width, int height>
|
|
static constexpr OamBuilder OamWithSize(const Point& position, u32 vramOffset)
|
|
{
|
|
return OamWithSize<width, height>(position.x, position.y, vramOffset);
|
|
}
|
|
|
|
template <int width, int height>
|
|
static constexpr OamBuilder OamWithSize(int x, int y, u32 vramOffset)
|
|
{
|
|
OamBuilder builder;
|
|
switch (width)
|
|
{
|
|
case 8:
|
|
{
|
|
switch (height)
|
|
{
|
|
case 8:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_8_8;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_8_8;
|
|
break;
|
|
case 16:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_8_16;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_8_16;
|
|
break;
|
|
case 32:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_8_32;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_8_32;
|
|
break;
|
|
default:
|
|
static_assert(width != 8 || (height == 8 || height == 16 || height == 32), "Invalid oam height for width 8");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 16:
|
|
{
|
|
switch (height)
|
|
{
|
|
case 8:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_16_8;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_16_8;
|
|
break;
|
|
case 16:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_16_16;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_16_16;
|
|
break;
|
|
case 32:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_16_32;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_16_32;
|
|
break;
|
|
default:
|
|
static_assert(width != 16 || (height == 8 || height == 16 || height == 32), "Invalid oam height for width 16");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 32:
|
|
{
|
|
switch (height)
|
|
{
|
|
case 8:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_32_8;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_32_8;
|
|
break;
|
|
case 16:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_32_16;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_32_16;
|
|
break;
|
|
case 32:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_32_32;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_32_32;
|
|
break;
|
|
case 64:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_32_64;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_32_64;
|
|
break;
|
|
default:
|
|
static_assert(width != 32 || (height == 8 || height == 16 || height == 32 || height == 64), "Invalid oam height for width 32");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 64:
|
|
{
|
|
switch (height)
|
|
{
|
|
case 32:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_64_32;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_64_32;
|
|
break;
|
|
case 64:
|
|
builder._attr0 = GFX_OAM_ATTR0_SHAPE_64_64;
|
|
builder._attr1 = GFX_OAM_ATTR1_SIZE_64_64;
|
|
break;
|
|
default:
|
|
static_assert(width != 64 || (height == 32 || height == 64), "Invalid oam height for width 64");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
static_assert(width == 8 || width == 16 || width == 32 || width == 64, "Invalid oam width");
|
|
break;
|
|
}
|
|
builder._attr0 |= GFX_OAM_ATTR0_Y(y);
|
|
builder._attr1 |= GFX_OAM_ATTR1_X(x);
|
|
builder._attr2 = GFX_OAM_ATTR2_VRAM_OFFS(vramOffset);
|
|
return builder;
|
|
}
|
|
|
|
constexpr OamBuilder& Hidden()
|
|
{
|
|
_attr0 &= ~GFX_OAM_ATTR0_DOUBLE_AFFINE;
|
|
_attr0 |= GFX_OAM_ATTR0_HIDDEN;
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& AsWindow()
|
|
{
|
|
_attr0 &= ~GFX_OAM_ATTR0_MODE_BITMAP;
|
|
_attr0 |= GFX_OAM_ATTR0_MODE_WINDOW;
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& AsTranslucent()
|
|
{
|
|
_attr0 &= ~GFX_OAM_ATTR0_MODE_BITMAP;
|
|
_attr0 |= GFX_OAM_ATTR0_MODE_TRANSLUCENT;
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& AsBitmap(int alpha = 16)
|
|
{
|
|
_attr0 &= ~GFX_OAM_ATTR0_PLTT256;
|
|
_attr0 |= GFX_OAM_ATTR0_MODE_BITMAP;
|
|
|
|
if (alpha == 0)
|
|
return Hidden();
|
|
|
|
_attr2 &= ~GFX_OAM_ATTR2_BMP_ALPHA(0xF);
|
|
_attr2 |= GFX_OAM_ATTR2_BMP_ALPHA(alpha - 1);
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& WithAffineMtx(int mtx, bool doubleSize = false)
|
|
{
|
|
_attr0 &= ~GFX_OAM_ATTR0_DOUBLE_AFFINE;
|
|
if (doubleSize)
|
|
_attr0 |= GFX_OAM_ATTR0_DOUBLE_AFFINE;
|
|
else
|
|
_attr0 |= GFX_OAM_ATTR0_AFFINE;
|
|
_attr1 &= ~GFX_OAM_ATTR1_MTX(0x1F);
|
|
_attr1 |= GFX_OAM_ATTR1_MTX(mtx);
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& WithHFlip(bool hFlip = true)
|
|
{
|
|
if (hFlip)
|
|
_attr1 |= GFX_OAM_ATTR1_HFLIP;
|
|
else
|
|
_attr1 &= ~GFX_OAM_ATTR1_HFLIP;
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& WithVFlip(bool vFlip = true)
|
|
{
|
|
if (vFlip)
|
|
_attr1 |= GFX_OAM_ATTR1_VFLIP;
|
|
else
|
|
_attr1 &= ~GFX_OAM_ATTR1_VFLIP;
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& WithPriority(int priority)
|
|
{
|
|
_attr2 &= ~GFX_OAM_ATTR2_PRIORITY(3);
|
|
_attr2 |= GFX_OAM_ATTR2_PRIORITY(priority);
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& WithPalette16(int palette)
|
|
{
|
|
_attr0 &= ~GFX_OAM_ATTR0_PLTT256;
|
|
_attr2 &= ~GFX_OAM_ATTR2_PLTT(0xF);
|
|
_attr2 |= GFX_OAM_ATTR2_PLTT(palette);
|
|
return *this;
|
|
}
|
|
|
|
constexpr OamBuilder& WithPalette256(int palette = 0)
|
|
{
|
|
_attr0 |= GFX_OAM_ATTR0_PLTT256;
|
|
_attr2 &= ~GFX_OAM_ATTR2_PLTT(0xF);
|
|
_attr2 |= GFX_OAM_ATTR2_PLTT(palette);
|
|
return *this;
|
|
}
|
|
|
|
constexpr void Build(gfx_oam_entry_t& oamEntry) const
|
|
{
|
|
oamEntry.attr0 = _attr0;
|
|
oamEntry.attr1 = _attr1;
|
|
oamEntry.attr2 = _attr2;
|
|
}
|
|
}; |