Begin transitioning to new CTexture; start Stream API

This commit is contained in:
Luke Street 2022-03-04 02:47:21 -05:00
parent 00fd243f62
commit 740114af9e
61 changed files with 1472 additions and 2075 deletions

View File

@ -1,20 +0,0 @@
#include "Runtime/CGameOptionsTouchBar.hpp"
namespace metaforce {
CGameOptionsTouchBar::EAction CGameOptionsTouchBar::PopAction() { return EAction::None; }
void CGameOptionsTouchBar::GetSelection(int& left, int& right, int& value) {
left = -1;
right = -1;
value = -1;
}
void CGameOptionsTouchBar::SetSelection([[maybe_unused]] int left, [[maybe_unused]] int right,
[[maybe_unused]] int value) {}
//#ifndef __APPLE__
std::unique_ptr<CGameOptionsTouchBar> NewGameOptionsTouchBar() { return std::make_unique<CGameOptionsTouchBar>(); }
//#endif
} // namespace metaforce

View File

@ -1,20 +0,0 @@
#pragma once
#include <memory>
#include <utility>
namespace metaforce {
class CGameOptionsTouchBar {
public:
enum class EAction { None, Back, Advance, ValueChange };
virtual ~CGameOptionsTouchBar() = default;
virtual EAction PopAction();
virtual void GetSelection(int& left, int& right, int& value);
virtual void SetSelection(int left, int right, int value);
};
std::unique_ptr<CGameOptionsTouchBar> NewGameOptionsTouchBar();
} // namespace metaforce

View File

@ -1,260 +0,0 @@
#include "CGameOptions.hpp"
#include "CGameOptionsTouchBar.hpp"
#include "GameGlobalObjects.hpp"
#include "GuiSys/CStringTable.hpp"
#include "MP1/MP1.hpp"
#include <AppKit/AppKit.h>
#if !__has_feature(objc_arc)
#error ARC Required
#endif
static NSColor *BlueConfirm() {
return [NSColor colorWithSRGBRed:0 / 255.f green:130 / 255.f blue:215 / 255.f alpha:1.f];
}
@interface GameOptionsTouchBar : NSObject <NSTouchBarDelegate> {
@public
metaforce::CStringTable *_pauseScreenStrg;
metaforce::CGameOptionsTouchBar::EAction _action;
std::pair<int, int> _selection;
int _value, _pendingValue;
}
- (IBAction)onBack:(id)sender;
- (IBAction)onSlide:(id)sender;
- (IBAction)onSet0:(id)sender;
- (IBAction)onSet1:(id)sender;
- (IBAction)onSet2:(id)sender;
- (IBAction)onLeft:(id)sender;
- (IBAction)onRight:(id)sender;
@end
@implementation GameOptionsTouchBar
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"optionsGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"optionsGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"optionsGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items;
if (_selection.first == -1) {
items = [NSMutableArray arrayWithCapacity:5];
[items addObject:@"back"];
for (int i = 0; i < 4; ++i)
[items addObject:[NSString stringWithFormat:@"left/%d", i]];
} else if (_selection.second == -1) {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
items = [NSMutableArray arrayWithCapacity:opt.first + 1];
[items addObject:@"back"];
for (int i = 0; i < opt.first; ++i)
[items addObject:[NSString stringWithFormat:@"right/%d", i]];
} else {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
const metaforce::SGameOption &subopt = opt.second[_selection.second];
if (subopt.type == metaforce::EOptionType::Float)
items = @[ @"back", @"value" ];
else if (subopt.type == metaforce::EOptionType::DoubleEnum)
items = @[ @"back", @"label", @"double0", @"double1" ];
else if (subopt.type == metaforce::EOptionType::TripleEnum)
items = @[ @"back", @"label", @"triple0", @"triple1", @"triple2" ];
}
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"back"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarGoBackTemplate]
target:self
action:@selector(onBack:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"label"]) {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
const metaforce::SGameOption &subopt = opt.second[_selection.second];
const char16_t *cStr = _pauseScreenStrg->GetString(subopt.stringId);
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSTextField *label = [NSTextField labelWithString:[str stringByAppendingString:@":"]];
item.view = label;
return item;
} else if ([identifier isEqualToString:@"value"]) {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
const metaforce::SGameOption &subopt = opt.second[_selection.second];
const char16_t *cStr = _pauseScreenStrg->GetString(subopt.stringId);
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSSliderTouchBarItem *item = [[NSSliderTouchBarItem alloc] initWithIdentifier:identifier];
NSSlider *slider = [NSSlider sliderWithValue:_value
minValue:subopt.minVal
maxValue:subopt.maxVal
target:nil
action:nil];
item.target = self;
item.action = @selector(onSlide:);
item.slider = slider;
item.label = str;
return item;
} else if ([identifier isEqualToString:@"double0"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(95); // Off
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet0:)];
if (_value == 0)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"double1"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(94); // On
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet1:)];
if (_value == 1)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"triple0"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(96); // Mono
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet0:)];
if (_value == 0)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"triple1"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(97); // Stereo
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet1:)];
if (_value == 1)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"triple2"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(98); // Dolby
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet2:)];
if (_value == 2)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else {
NSArray<NSString *> *pc = [identifier pathComponents];
if ([pc count] == 2) {
NSString *first = [pc objectAtIndex:0];
if ([first isEqualToString:@"left"]) {
auto idx = strtoul([[pc objectAtIndex:1] UTF8String], nullptr, 10);
const char16_t *cStr = _pauseScreenStrg->GetString(16 + idx);
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onLeft:)];
button.tag = idx;
item.view = button;
return item;
} else if ([first isEqualToString:@"right"]) {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
auto idx = strtoul([[pc objectAtIndex:1] UTF8String], nullptr, 10);
const metaforce::SGameOption &subopt = opt.second[idx];
const char16_t *cStr = _pauseScreenStrg->GetString(subopt.stringId);
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onRight:)];
button.tag = idx;
item.view = button;
return item;
}
}
}
return nil;
}
- (IBAction)onBack:(id)sender {
_action = metaforce::CGameOptionsTouchBar::EAction::Back;
}
- (IBAction)onSlide:(id)sender {
_pendingValue = [((NSSliderTouchBarItem *)sender).slider intValue];
_action = metaforce::CGameOptionsTouchBar::EAction::ValueChange;
}
- (IBAction)onSet0:(id)sender {
_pendingValue = 0;
_action = metaforce::CGameOptionsTouchBar::EAction::ValueChange;
}
- (IBAction)onSet1:(id)sender {
_pendingValue = 1;
_action = metaforce::CGameOptionsTouchBar::EAction::ValueChange;
}
- (IBAction)onSet2:(id)sender {
_pendingValue = 2;
_action = metaforce::CGameOptionsTouchBar::EAction::ValueChange;
}
- (IBAction)onLeft:(id)sender {
_selection.first = ((NSButton *)sender).tag;
_action = metaforce::CGameOptionsTouchBar::EAction::Advance;
}
- (IBAction)onRight:(id)sender {
_selection.second = ((NSButton *)sender).tag;
_action = metaforce::CGameOptionsTouchBar::EAction::Advance;
}
@end
namespace metaforce {
class CGameOptionsTouchBarMac : public CGameOptionsTouchBar {
TLockedToken<CStringTable> m_pauseScreen;
GameOptionsTouchBar *m_touchBar;
bool m_initialized = false;
public:
CGameOptionsTouchBarMac() {
m_pauseScreen = g_SimplePool->GetObj("STRG_PauseScreen");
m_touchBar = [GameOptionsTouchBar new];
m_touchBar->_pauseScreenStrg = m_pauseScreen.GetObj();
m_touchBar->_selection = std::make_pair(-1, -1);
m_touchBar->_value = -1;
}
EAction PopAction() {
if (m_touchBar->_action != EAction::None) {
EAction action = m_touchBar->_action;
m_touchBar->_action = EAction::None;
return action;
}
return EAction::None;
}
void GetSelection(int &left, int &right, int &value) {
left = m_touchBar->_selection.first;
right = m_touchBar->_selection.second;
value = m_touchBar->_pendingValue;
}
void SetSelection(int left, int right, int value) {
if (m_initialized && left == m_touchBar->_selection.first && right == m_touchBar->_selection.second &&
value == m_touchBar->_value)
return;
m_initialized = true;
m_touchBar->_selection = std::make_pair(left, right);
m_touchBar->_value = value;
g_Main->GetMainWindow()->setTouchBarProvider((__bridge_retained void *)m_touchBar);
}
};
std::unique_ptr<CGameOptionsTouchBar> NewGameOptionsTouchBar() { return std::make_unique<CGameOptionsTouchBarMac>(); }
}

View File

@ -110,7 +110,6 @@ set(RUNTIME_SOURCES_B
IObjectStore.hpp
CSimplePool.hpp CSimplePool.cpp
CGameOptions.hpp CGameOptions.cpp
CGameOptionsTouchBar.hpp CGameOptionsTouchBar.cpp
CStaticInterference.hpp CStaticInterference.cpp
CCRC32.hpp CCRC32.cpp
IFactory.hpp

View File

@ -171,38 +171,39 @@ std::pair<CAssetId, TAreaId> CMemoryCardSys::GetAreaAndWorldIdForSaveId(s32 save
void CMemoryCardSys::CCardFileInfo::LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp) {
x3c_bannerTex = bannerTxtr;
x40_bannerTok.emplace(sp.GetObj({FOURCC('TXTR'), bannerTxtr}, m_texParam));
x40_bannerTok.emplace(sp.GetObj({FOURCC('TXTR'), bannerTxtr}));
}
CMemoryCardSys::CCardFileInfo::Icon::Icon(CAssetId id, kabufuda::EAnimationSpeed speed, CSimplePool& sp,
const CVParamTransfer& cv)
: x0_id(id), x4_speed(speed), x8_tex(sp.GetObj({FOURCC('TXTR'), id}, cv)) {}
CMemoryCardSys::CCardFileInfo::Icon::Icon(CAssetId id, kabufuda::EAnimationSpeed speed, CSimplePool& sp)
: x0_id(id), x4_speed(speed), x8_tex(sp.GetObj({FOURCC('TXTR'), id})) {}
void CMemoryCardSys::CCardFileInfo::LockIconToken(CAssetId iconTxtr, kabufuda::EAnimationSpeed speed, CSimplePool& sp) {
x50_iconToks.emplace_back(iconTxtr, speed, sp, m_texParam);
x50_iconToks.emplace_back(iconTxtr, speed, sp);
}
u32 CMemoryCardSys::CCardFileInfo::CalculateBannerDataSize() const {
u32 ret = 68;
if (x3c_bannerTex.IsValid()) {
if ((*x40_bannerTok)->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3)
if ((*x40_bannerTok)->GetTextureFormat() == ETexelFormat::RGB5A3) {
ret = 6212;
else
} else {
ret = 3652;
}
}
bool paletteTex = false;
for (const Icon& icon : x50_iconToks) {
if (icon.x8_tex->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3)
if (icon.x8_tex->GetTextureFormat() == ETexelFormat::RGB5A3) {
ret += 2048;
else {
} else {
ret += 1024;
paletteTex = true;
}
}
if (paletteTex)
if (paletteTex) {
ret += 512;
}
return ret;
}
@ -233,35 +234,36 @@ void CMemoryCardSys::CCardFileInfo::BuildCardBuffer() {
void CMemoryCardSys::CCardFileInfo::WriteBannerData(COutputStream& out) const {
if (x3c_bannerTex.IsValid()) {
const TLockedToken<CTexture>& tex = *x40_bannerTok;
u32 bufSz;
ETexelFormat fmt;
std::unique_ptr<u8[]> palette;
std::unique_ptr<u8[]> texels = tex->BuildMemoryCardTex(bufSz, fmt, palette);
if (fmt == ETexelFormat::RGB5A3)
out.Write(texels.get(), 6144);
else
out.Write(texels.get(), 3072);
if (fmt == ETexelFormat::C8)
out.Write(palette.get(), 512);
const auto format = tex->GetTextureFormat();
const auto* texels = tex->GetConstBitMapData(0);
if (format == ETexelFormat::RGB5A3) {
out.Write(texels, 6144);
} else {
out.Write(texels, 3072);
}
if (format == ETexelFormat::C8) {
out.Write(tex->GetPalette()->GetEntries(), 512);
}
}
}
void CMemoryCardSys::CCardFileInfo::WriteIconData(COutputStream& out) const {
std::unique_ptr<u8[]> palette;
const u8* palette = nullptr;
for (const Icon& icon : x50_iconToks) {
u32 bufSz;
ETexelFormat fmt;
std::unique_ptr<u8[]> texels = icon.x8_tex->BuildMemoryCardTex(bufSz, fmt, palette);
if (fmt == ETexelFormat::RGB5A3)
out.Write(texels.get(), 2048);
else
out.Write(texels.get(), 1024);
const auto format = icon.x8_tex->GetTextureFormat();
const auto* texels = icon.x8_tex->GetConstBitMapData(0);
if (format == ETexelFormat::RGB5A3) {
out.Write(texels, 2048);
} else {
out.Write(texels, 1024);
}
if (format == ETexelFormat::C8) {
palette = icon.x8_tex->GetPalette()->GetEntries();
}
}
if (palette != nullptr) {
out.Write(palette, 512);
}
if (palette)
out.Write(palette.get(), 512);
}
ECardResult CMemoryCardSys::CCardFileInfo::PumpCardTransfer() {
@ -292,26 +294,29 @@ ECardResult CMemoryCardSys::CCardFileInfo::PumpCardTransfer() {
ECardResult CMemoryCardSys::CCardFileInfo::GetStatus(kabufuda::CardStat& stat) const {
ECardResult result = CMemoryCardSys::GetStatus(m_handle.slot, m_handle.getFileNo(), stat);
if (result != ECardResult::READY)
if (result != ECardResult::READY) {
return result;
}
stat.SetCommentAddr(4);
stat.SetIconAddr(68);
kabufuda::EImageFormat bannerFmt;
if (x3c_bannerTex.IsValid()) {
if ((*x40_bannerTok)->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3)
if ((*x40_bannerTok)->GetTextureFormat() == ETexelFormat::RGB5A3) {
bannerFmt = kabufuda::EImageFormat::RGB5A3;
else
} else {
bannerFmt = kabufuda::EImageFormat::C8;
} else
}
} else {
bannerFmt = kabufuda::EImageFormat::None;
}
stat.SetBannerFormat(bannerFmt);
int idx = 0;
for (const Icon& icon : x50_iconToks) {
stat.SetIconFormat(icon.x8_tex->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3 ? kabufuda::EImageFormat::RGB5A3
: kabufuda::EImageFormat::C8,
stat.SetIconFormat(icon.x8_tex->GetTextureFormat() == ETexelFormat::RGB5A3 ? kabufuda::EImageFormat::RGB5A3
: kabufuda::EImageFormat::C8,
idx);
stat.SetIconSpeed(icon.x4_speed, idx);
++idx;
@ -555,9 +560,8 @@ void CMemoryCardSys::CommitToDisk(kabufuda::ECardSlot port) {
}
bool CMemoryCardSys::CreateDolphinCard(kabufuda::ECardSlot slot) {
std::string path =
_CreateDolphinCard(slot, slot == kabufuda::ECardSlot::SlotA ? mc_dolphinAPath->hasDefaultValue()
: mc_dolphinBPath->hasDefaultValue());
std::string path = _CreateDolphinCard(slot, slot == kabufuda::ECardSlot::SlotA ? mc_dolphinAPath->hasDefaultValue()
: mc_dolphinBPath->hasDefaultValue());
if (CardProbe(slot).x0_error != ECardResult::READY) {
return false;
}

View File

@ -115,7 +115,7 @@ public:
CAssetId x0_id;
kabufuda::EAnimationSpeed x4_speed;
TLockedToken<CTexture> x8_tex;
Icon(CAssetId id, kabufuda::EAnimationSpeed speed, CSimplePool& sp, const CVParamTransfer& cv);
Icon(CAssetId id, kabufuda::EAnimationSpeed speed, CSimplePool& sp);
};
enum class EStatus { Standby, Transferring, Done };
@ -131,8 +131,6 @@ public:
std::vector<u8> xf4_saveBuffer;
std::vector<u8> x104_cardBuffer;
CVParamTransfer m_texParam = {new TObjOwnerParam<u32>(SBIG('OTEX'))};
CCardFileInfo(kabufuda::ECardSlot port, std::string_view name) : m_handle(port), x18_fileName(name) {}
void LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp);

View File

@ -54,7 +54,7 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur
materialDataCur += 8;
for (u32 i = 0; i < texCount; ++i) {
u32 texIdx = SBig(*reinterpret_cast<const u32*>(materialDataCur));
sRenderingModel->GetTexture(texIdx)->Load(i, CTexture::EClampMode::Repeat);
sRenderingModel->GetTexture(texIdx)->Load(static_cast<GX::TexMapID>(i), EClampMode::Repeat);
materialDataCur += 4;
}
}
@ -423,7 +423,7 @@ void CCubeMaterial::DoPassthru(u32 finalTevCount) {
}
void CCubeMaterial::DoModelShadow(u32 texCount, u32 tcgCount) {
// CCubeModel::sShadowTexture->Load(texCount, CTexture::EClampMode::One);
// CCubeModel::sShadowTexture->Load(texCount, EClampMode::One);
// TODO
}
} // namespace metaforce

View File

@ -14,71 +14,6 @@ class CCubeModel;
class CCubeSurface;
struct CModelFlags;
template <typename BitType>
class Flags {
public:
using MaskType = typename std::underlying_type<BitType>::type;
// constructors
constexpr Flags() noexcept : m_mask(0) {}
constexpr Flags(BitType bit) noexcept : m_mask(static_cast<MaskType>(bit)) {}
constexpr Flags(Flags<BitType> const& rhs) noexcept : m_mask(rhs.m_mask) {}
constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {}
[[nodiscard]] constexpr bool IsSet(Flags<BitType> const bit) const noexcept { return bool(*this & bit); }
// relational operators
auto operator<=>(Flags<BitType> const&) const noexcept = default;
// logical operator
constexpr bool operator!() const noexcept { return !m_mask; }
// bitwise operators
constexpr Flags<BitType> operator&(Flags<BitType> const& rhs) const noexcept {
return Flags<BitType>(m_mask & rhs.m_mask);
}
constexpr Flags<BitType> operator|(Flags<BitType> const& rhs) const noexcept {
return Flags<BitType>(m_mask | rhs.m_mask);
}
constexpr Flags<BitType> operator^(Flags<BitType> const& rhs) const noexcept {
return Flags<BitType>(m_mask ^ rhs.m_mask);
}
// assignment operators
constexpr Flags<BitType>& operator=(Flags<BitType> const& rhs) noexcept {
m_mask = rhs.m_mask;
return *this;
}
constexpr Flags<BitType>& operator|=(Flags<BitType> const& rhs) noexcept {
m_mask |= rhs.m_mask;
return *this;
}
constexpr Flags<BitType>& operator&=(Flags<BitType> const& rhs) noexcept {
m_mask &= rhs.m_mask;
return *this;
}
constexpr Flags<BitType>& operator^=(Flags<BitType> const& rhs) noexcept {
m_mask ^= rhs.m_mask;
return *this;
}
// cast operators
explicit constexpr operator bool() const noexcept { return m_mask != 0; }
explicit constexpr operator MaskType() const noexcept { return m_mask; }
private:
MaskType m_mask;
};
enum class CCubeMaterialFlagBits : u32 {
fKonstValues = 0x8,
fDepthSorting = 0x10,

View File

@ -64,11 +64,11 @@ private:
std::optional<CPVSVisSet> xc8_pvs;
bool xdc_{};
u32 xe0_pvsAreaIdx = UINT32_MAX;
CTexture xe4_blackTex{ETexelFormat::RGB565, 4, 4, 1};
CTexture xe4_blackTex{ETexelFormat::RGB565, 4, 4, 1, "Black Texture"};
std::unique_ptr<CTexture> x14c_reflectionTex;
CTexture x150_reflectionTex{ETexelFormat::IA8, 32, 32, 1};
CTexture x1b8_fogVolumeRamp{ETexelFormat::I8, 256, 256, 1};
CTexture x220_sphereRamp{ETexelFormat::I8, 32, 32, 1};
CTexture x150_reflectionTex{ETexelFormat::IA8, 32, 32, 1, "Reflection Texture"};
CTexture x1b8_fogVolumeRamp{ETexelFormat::I8, 256, 256, 1, "Fog Volume Ramp Texture"};
CTexture x220_sphereRamp{ETexelFormat::I8, 32, 32, 1, "Sphere Ramp Texture"};
// CGraphicsPalette x288_thermoPalette{1, 16};
CRandom16 x2a8_thermalRand{20};
std::list<CFogVolumeListItem> x2ac_fogVolumes;

View File

@ -12,8 +12,8 @@ std::unique_ptr<CTexture> CFont::mpTexture;
CFont::CFont(float scale) : x0_fontSize(16.f * scale), x4_scale(scale) {
if (sNumInstances == 0) {
mpTexture = std::make_unique<CTexture>(ETexelFormat::I8, 256, 256, 1);
u8* fontData = new u8[(mpTexture->GetBitsPerPixel() * mpTexture->GetWidth() * mpTexture->GetHeight()) / 8];
mpTexture = std::make_unique<CTexture>(ETexelFormat::I8, 256, 256, 1, "Font Texture");
u8* fontData = new u8[(mpTexture->GetBitDepth() * mpTexture->GetWidth() * mpTexture->GetHeight()) / 8];
memcpy(fontData, sSystemFont.data(), sSystemFont.size());
// u8* textureData = mpTexture->GetBitMapData();
// LinearToTile8(textureData, fontData);

View File

@ -511,58 +511,61 @@ void CGraphics::SetCopyClear(const zeus::CColor& color, float depth) {
void CGraphics::SetIsBeginSceneClearFb(bool clear) { g_IsBeginSceneClearFb = clear; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a564c{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
};
// Stream API
static EStreamFlags sStreamFlags;
static zeus::CColor sQueuedColor;
static zeus::CVector2f sQueuedTexCoord;
static zeus::CVector3f sQueuedNormal;
const CTevCombiners::CTevPass CGraphics::sTevPass805a5698{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_C0, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_A0, GX::TevAlphaArg::CA_ZERO},
};
void CGraphics::SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass) {
CTevCombiners::SetupPass(stage, pass);
}
const CTevCombiners::CTevPass CGraphics::sTevPass805a5e70{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_C0},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_A0},
};
void CGraphics::StreamBegin(GX::Primitive primitive) {
sStreamFlags = {};
aurora::gfx::stream_begin(primitive);
}
const CTevCombiners::CTevPass CGraphics::sTevPass805a5ebc{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_ZERO},
};
void CGraphics::StreamNormal(const zeus::CVector3f& nrm) {
sQueuedNormal = nrm;
sStreamFlags |= EStreamFlagBits::fHasNormal;
}
const CTevCombiners::CTevPass CGraphics::sTevPass805a5f08{
{GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_TEXA, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
};
void CGraphics::StreamColor(float r, float g, float b, float a) {
sQueuedColor = zeus::CColor{r, g, b, a};
sStreamFlags |= EStreamFlagBits::fHasColor;
}
const CTevCombiners::CTevPass CGraphics::sTevPass805a5f54{
{GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ONE, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
};
void CGraphics::StreamColor(const zeus::CColor& color) {
sQueuedColor = color;
sStreamFlags |= EStreamFlagBits::fHasColor;
}
const CTevCombiners::CTevPass CGraphics::sTevPass805a5fa0{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA},
};
void CGraphics::StreamTexcoord(float x, float y) {
sQueuedTexCoord = {x, y};
sStreamFlags |= EStreamFlagBits::fHasTexture;
}
const CTevCombiners::CTevPass CGraphics::sTevPass804bfcc0{
{GX::TevColorArg::CC_C0, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
};
void CGraphics::StreamTexcoord(const zeus::CVector2f& uv) {
sQueuedTexCoord = uv;
sStreamFlags |= EStreamFlagBits::fHasTexture;
}
const CTevCombiners::CTevPass CGraphics::sTevPass805a5fec{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
};
void CGraphics::StreamVertex(float xyz) {
const zeus::CVector3f pos{xyz, xyz, xyz};
aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
}
const CTevCombiners::CTevPass CGraphics::sTevPass805a6038{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_KONST, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
};
void CGraphics::StreamVertex(float x, float y, float z) {
const zeus::CVector3f pos{x, y, z};
aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
}
const CTevCombiners::CTevPass CGraphics::sTevPass805a6084{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_CPREV, GX::TevColorArg::CC_APREV, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_APREV},
};
void CGraphics::StreamVertex(const zeus::CVector3f& pos) {
aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
}
void CGraphics::StreamEnd() {
aurora::gfx::stream_end();
}
} // namespace metaforce

View File

@ -1,23 +1,21 @@
#pragma once
#include "Runtime/RetroTypes.hpp"
#include "Runtime/Graphics/GX.hpp"
#include "Runtime/Graphics/CTevCombiners.hpp"
#include "Runtime/ConsoleVariables/CVar.hpp"
#include <array>
#include <chrono>
#include <vector>
#include "optick.h"
#include "Runtime/RetroTypes.hpp"
#include "Runtime/Graphics/GX.hpp"
#include "Runtime/ConsoleVariables/CVar.hpp"
#include <zeus/CColor.hpp>
#include <zeus/CTransform.hpp>
#include <zeus/CVector2f.hpp>
#include <zeus/CVector2i.hpp>
#include <aurora/gfx.hpp>
#include <optick.h>
using frame_clock = std::chrono::high_resolution_clock;
@ -94,25 +92,6 @@ struct SClipScreenRect {
}
};
enum class ETexelFormat {
Invalid = -1,
I4 = 0,
I8 = 1,
IA4 = 2,
IA8 = 3,
C4 = 4,
C8 = 5,
C14X2 = 6,
RGB565 = 7,
RGB5A3 = 8,
RGBA8 = 9,
CMPR = 10,
RGBA8PC = 16,
C8PC = 17,
CMPRPC = 18,
CMPRPCA = 19,
};
#define DEPTH_FAR 1.f
#define DEPTH_SKY 0.999f
#define DEPTH_TARGET_MANAGER 0.12500012f
@ -124,47 +103,6 @@ enum class ETexelFormat {
#define CUBEMAP_RES 256
#define CUBEMAP_MIPS 6
static s32 sNextUniquePass = 0;
namespace CTevCombiners {
struct CTevOp {
bool x0_clamp = true;
GX::TevOp x4_op = GX::TevOp::TEV_ADD;
GX::TevBias x8_bias = GX::TevBias::TB_ZERO;
GX::TevScale xc_scale = GX::TevScale::CS_SCALE_1;
GX::TevRegID xc_regId = GX::TevRegID::TEVPREV;
};
struct ColorPass {
GX::TevColorArg x0_a;
GX::TevColorArg x4_b;
GX::TevColorArg x8_c;
GX::TevColorArg xc_d;
};
struct AlphaPass {
GX::TevAlphaArg x0_a;
GX::TevAlphaArg x4_b;
GX::TevAlphaArg x8_c;
GX::TevAlphaArg xc_d;
};
class CTevPass {
u32 x0_id;
ColorPass x4_colorPass;
AlphaPass x14_alphaPass;
CTevOp x24_colorOp;
CTevOp x38_alphaOp;
public:
CTevPass(const ColorPass& colPass, const AlphaPass& alphaPass, const CTevOp& colorOp = CTevOp(),
const CTevOp alphaOp = CTevOp())
: x0_id(++sNextUniquePass)
, x4_colorPass(colPass)
, x14_alphaPass(alphaPass)
, x24_colorOp(colorOp)
, x38_alphaOp(alphaOp) {}
};
}; // namespace CTevCombiners
class CGraphics {
public:
struct CProjectionState {
@ -352,26 +290,17 @@ public:
// static void DrawArray(size_t start, size_t count) { g_BooMainCommandQueue->draw(start, count); }
// static void DrawArrayIndexed(size_t start, size_t count) { g_BooMainCommandQueue->drawIndexed(start, count); }
static const CTevCombiners::CTevPass sTevPass805a564c;
static const CTevCombiners::CTevPass sTevPass805a5698;
static const CTevCombiners::CTevPass sTevPass805a5e70;
static const CTevCombiners::CTevPass sTevPass805a5ebc;
static const CTevCombiners::CTevPass sTevPass805a5f08;
static const CTevCombiners::CTevPass sTevPass805a5f54;
static const CTevCombiners::CTevPass sTevPass805a5fa0;
static const CTevCombiners::CTevPass sTevPass804bfcc0;
static const CTevCombiners::CTevPass sTevPass805a5fec;
static const CTevCombiners::CTevPass sTevPass805a6038;
static const CTevCombiners::CTevPass sTevPass805a6084;
static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass);
static void StreamBegin(GX::Primitive primitive);
static void StreamNormal(const zeus::CVector3f& nrm);
static void StreamColor(float r, float g, float b, float a);
static void StreamColor(const zeus::CColor& color);
static void StreamTexcoord(float x, float y);
static void StreamTexcoord(const zeus::CVector2f& uv);
static void StreamVertex(float xyz);
static void StreamVertex(float x, float y, float z);
static void StreamVertex(const zeus::CVector3f& pos);
static void StreamEnd();
};
template <class VTX>

View File

@ -1,7 +1,8 @@
#pragma once
#include "RetroTypes.hpp"
#include <memory>
#include "Runtime/RetroTypes.hpp"
namespace metaforce {
class CInputStream;
@ -24,10 +25,12 @@ class CGraphicsPalette {
public:
explicit CGraphicsPalette(EPaletteFormat fmt, int count);
explicit CGraphicsPalette(CInputStream& in);
void Load();
[[nodiscard]] const u8* GetEntries() const { return xc_entries.get(); }
static void SetCurrentFrameCount(u32 frameCount) { sCurrentFrameCount = frameCount; }
};

View File

@ -10,8 +10,8 @@ set(GRAPHICS_SOURCES
CLineRenderer.hpp CLineRenderer.cpp
CMetroidModelInstance.cpp CMetroidModelInstance.hpp
CLight.hpp CLight.cpp
DolphinCTexture.hpp DolphinCTexture.cpp
CTexture.hpp CTextureBoo.cpp
CTevCombiners.cpp CTevCombiners.hpp
CTexture.hpp CTexture.cpp
CModel.cpp CModel.hpp
CSkinnedModel.hpp CSkinnedModel.cpp
CVertexMorphEffect.hpp CVertexMorphEffect.cpp

View File

@ -1,8 +1,10 @@
#include "Runtime/Graphics/CMoviePlayer.hpp"
#include "Graphics/CMoviePlayer.hpp"
#include "Runtime/Audio/g721.h"
#include "Runtime/CDvdRequest.hpp"
#include "Runtime/Graphics/CGraphics.hpp"
#include "Audio/g721.h"
#include "CDvdRequest.hpp"
#include "Graphics/CGraphics.hpp"
#include "Graphics/CCubeRenderer.hpp"
#include "GameGlobalObjects.hpp"
#include <amuse/DSPCodec.hpp>
#include <turbojpeg.h>
@ -190,29 +192,28 @@ CMoviePlayer::CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bo
CTHPTextureSet& set = x80_textures.emplace_back();
if (deinterlace) {
/* metaforce addition: this way interlaced THPs don't look horrible */
set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height / 2, 1,
aurora::gfx::TextureFormat::R8,
fmt::format(FMT_STRING("Movie {} Texture Set {} Y[0]"), path, i));
set.Y[1] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height / 2, 1,
aurora::gfx::TextureFormat::R8,
fmt::format(FMT_STRING("Movie {} Texture Set {} Y[1]"), path, i));
set.U = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1,
aurora::gfx::TextureFormat::R8,
fmt::format(FMT_STRING("Movie {} Texture Set {} U"), path, i));
set.V = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1,
aurora::gfx::TextureFormat::R8,
fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i));
set.Y[0] =
aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height / 2, 1, ETexelFormat::R8PC,
fmt::format(FMT_STRING("Movie {} Texture Set {} Y[0]"), path, i));
set.Y[1] =
aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height / 2, 1, ETexelFormat::R8PC,
fmt::format(FMT_STRING("Movie {} Texture Set {} Y[1]"), path, i));
set.U =
aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, ETexelFormat::R8PC,
fmt::format(FMT_STRING("Movie {} Texture Set {} U"), path, i));
set.V =
aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, ETexelFormat::R8PC,
fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i));
} else {
/* normal progressive presentation */
set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height, 1,
aurora::gfx::TextureFormat::R8,
set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height, 1, ETexelFormat::R8PC,
fmt::format(FMT_STRING("Movie {} Texture Set {} Y"), path, i));
set.U = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1,
aurora::gfx::TextureFormat::R8,
fmt::format(FMT_STRING("Movie {} Texture Set {} U"), path, i));
set.V = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1,
aurora::gfx::TextureFormat::R8,
fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i));
set.U =
aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, ETexelFormat::R8PC,
fmt::format(FMT_STRING("Movie {} Texture Set {} U"), path, i));
set.V =
aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, ETexelFormat::R8PC,
fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i));
}
if (xf4_25_hasAudio)
set.audioBuf.reset(new s16[x28_thpHead.maxAudioSamples * 2]);
@ -364,20 +365,37 @@ void CMoviePlayer::Rewind() {
xe8_curSeconds = 0.f;
}
void CMoviePlayer::SetFrame(float hpad, float vpad) {
m_hpad = hpad;
m_vpad = vpad;
void CMoviePlayer::Draw() {
if (GetIsFullyCached()) {
g_Renderer->SetDepthReadWrite(false, false);
g_Renderer->SetViewportOrtho(false, -4096.f, 4096.f);
const auto vpHeight = CGraphics::GetViewportHeight();
const auto vpWidth = CGraphics::GetViewportWidth();
const auto vpTop = CGraphics::GetViewportTop();
const auto vpLeft = CGraphics::GetViewportLeft();
const auto [width, height] = GetVideoDimensions();
const auto centerX = (width - vpWidth) / 2;
const auto centerY = (height - vpHeight) / 2;
DrawFrame(vpLeft - centerX, vpLeft + vpWidth + centerX, vpTop - centerY, vpTop + vpHeight + centerY);
}
}
void CMoviePlayer::DrawFrame() {
void CMoviePlayer::DrawFrame(u32 left, u32 right, u32 top, u32 bottom) {
DrawFrame({static_cast<float>(left), 0.f, static_cast<float>(bottom)},
{static_cast<float>(right), 0.f, static_cast<float>(bottom)},
{static_cast<float>(left), 0.f, static_cast<float>(top)},
{static_cast<float>(right), 0.f, static_cast<float>(top)});
}
void CMoviePlayer::DrawFrame(const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
const zeus::CVector3f& v4) {
if (xd0_drawTexSlot == UINT32_MAX)
return;
SCOPED_GRAPHICS_DEBUG_GROUP("CMoviePlayer::DrawFrame", zeus::skYellow);
/* draw appropriate field */
CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot];
aurora::gfx::queue_movie_player(tex.Y[m_deinterlace ? (xfc_fieldIndex != 0) : 0], tex.U, tex.V, zeus::skWhite, m_hpad,
m_vpad);
aurora::gfx::queue_movie_player(tex.Y[m_deinterlace ? (xfc_fieldIndex != 0) : 0], tex.U, tex.V, v1, v2, v3, v4);
/* ensure second field is being displayed by VI to signal advance
* (faked in metaforce with continuous xor) */

View File

@ -109,10 +109,14 @@ private:
float m_hpad;
float m_vpad;
static u32 THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo);
void DecodeFromRead(const void* data);
void ReadCompleted();
void DrawFrame(u32 left, u32 right, u32 top, u32 bottom);
void DrawFrame(const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
const zeus::CVector3f& v4);
void PostDVDReadRequestIfNeeded();
void ReadCompleted();
static u32 THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo);
public:
CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bool deinterlace);
@ -135,8 +139,7 @@ public:
float GetPlayedSeconds() const { return xdc_frameRem + xe8_curSeconds; }
float GetTotalSeconds() const { return xe4_totalSeconds; }
void SetPlayMode(EPlayMode mode) { xe0_playMode = mode; }
void SetFrame(float hpad, float vpad);
void DrawFrame();
void Draw();
void Update(float dt);
std::pair<u32, u32> GetVideoDimensions() const { return {x6c_videoInfo.width, x6c_videoInfo.height}; }

View File

@ -0,0 +1,102 @@
#include "Graphics/CTevCombiners.hpp"
namespace metaforce::CTevCombiners {
u32 CTevPass::sNextUniquePass = 0;
void CTevPass::Execute(ERglTevStage stage) const {
aurora::gfx::update_tev_stage(stage, x4_colorPass, x14_alphaPass, x24_colorOp, x38_alphaOp);
}
constexpr u32 maxTevPasses = 2;
static u32 sNumEnabledPasses;
static std::array<bool, maxTevPasses> sValidPasses;
const CTevPass skPassThru{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
};
const CTevPass sTevPass805a5698{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_C0, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_A0, GX::TevAlphaArg::CA_ZERO},
};
const CTevPass sTevPass805a5e70{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_C0},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_A0},
};
const CTevPass sTevPass805a5ebc{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_ZERO},
};
const CTevPass sTevPass805a5f08{
{GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_TEXA, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
};
const CTevPass sTevPass805a5f54{
{GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ONE, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
};
const CTevPass sTevPass805a5fa0{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA},
};
const CTevPass sTevPass804bfcc0{
{GX::TevColorArg::CC_C0, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
};
const CTevPass sTevPass805a5fec{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
};
const CTevPass sTevPass805a6038{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_KONST, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
};
const CTevPass sTevPass805a6084{
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_CPREV, GX::TevColorArg::CC_APREV, GX::TevColorArg::CC_ZERO},
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_APREV},
};
void Init() {
sNumEnabledPasses = maxTevPasses;
sValidPasses.fill(true);
for (int i = 0; i < maxTevPasses; ++i) {
DeletePass(static_cast<ERglTevStage>(i));
}
sValidPasses.fill(false);
RecomputePasses();
}
void SetupPass(ERglTevStage stage, const CTevPass& pass) {
if (pass == skPassThru) {
DeletePass(stage);
return;
}
if (SetPassCombiners(stage, pass)) {
sValidPasses[static_cast<size_t>(stage)] = true;
RecomputePasses();
}
}
void DeletePass(ERglTevStage stage) {
SetPassCombiners(stage, skPassThru);
sValidPasses[static_cast<size_t>(stage)] = false;
RecomputePasses();
}
bool SetPassCombiners(ERglTevStage stage, const CTevPass& pass) {
pass.Execute(stage);
return true;
}
void RecomputePasses() {
sNumEnabledPasses = std::count(sValidPasses.begin(), sValidPasses.end(), true);
// CGX::SetNumTevStages(sNumEnabledPasses);
}
void ResetStates() {
sValidPasses.fill(false);
skPassThru.Execute(ERglTevStage::Stage0);
sNumEnabledPasses = 1;
// CGX::SetNumTevStages(1);
}
} // namespace metaforce::CTevCombiners

View File

@ -0,0 +1,49 @@
#pragma once
#include "Graphics/GX.hpp"
#include "RetroTypes.hpp"
#include <aurora/gfx.hpp>
namespace metaforce::CTevCombiners {
class CTevPass {
u32 x0_id;
ColorPass x4_colorPass;
AlphaPass x14_alphaPass;
CTevOp x24_colorOp;
CTevOp x38_alphaOp;
static u32 sNextUniquePass;
public:
CTevPass(const ColorPass& colPass, const AlphaPass& alphaPass, const CTevOp& colorOp = {}, const CTevOp& alphaOp = {})
: x0_id(++sNextUniquePass)
, x4_colorPass(colPass)
, x14_alphaPass(alphaPass)
, x24_colorOp(colorOp)
, x38_alphaOp(alphaOp) {}
void Execute(ERglTevStage stage) const;
bool operator<=>(const CTevPass&) const = default;
};
extern const CTevPass skPassThru;
extern const CTevPass sTevPass805a5698;
extern const CTevPass sTevPass805a5e70;
extern const CTevPass sTevPass805a5ebc;
extern const CTevPass sTevPass805a5f08;
extern const CTevPass sTevPass805a5f54;
extern const CTevPass sTevPass805a5fa0;
extern const CTevPass sTevPass804bfcc0;
extern const CTevPass sTevPass805a5fec;
extern const CTevPass sTevPass805a6038;
extern const CTevPass sTevPass805a6084;
void Init();
void SetupPass(ERglTevStage stage, const CTevPass& pass);
void DeletePass(ERglTevStage stage);
bool SetPassCombiners(ERglTevStage stage, const CTevPass& pass);
void RecomputePasses();
void ResetStates();
} // namespace metaforce::CTevCombiners

View File

@ -1,7 +1,9 @@
#include "Runtime/Graphics/DolphinCTexture.hpp"
#include "Graphics/CTexture.hpp"
#include "Runtime/CToken.hpp"
#include "zeus/Math.hpp"
#include "CToken.hpp"
#include <zeus/Math.hpp>
#include <magic_enum.hpp>
u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, bool mipmap, u8 max_lod) {
s32 shiftX = 0;
@ -70,30 +72,29 @@ u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, bool mipmap, u8 max_lo
return bufLen;
}
namespace metaforce::WIP {
namespace {
namespace metaforce {
static std::array<CTexture*, GX::MAX_TEXMAP> sLoadedTextures{};
}
CTexture::CTexture(ETexelFormat fmt, s16 w, s16 h, s32 mips)
CTexture::CTexture(ETexelFormat fmt, u16 w, u16 h, s32 mips, std::string_view label)
: x0_fmt(fmt)
, x4_w(w)
, x6_h(h)
, x8_mips(mips)
, x9_bitsPerPixel(TexelFormatBitsPerPixel(fmt))
, x64_frameAllocated(sCurrentFrameCount) {
, x64_frameAllocated(sCurrentFrameCount)
, m_label(fmt::format(FMT_STRING("{} ({})"), label, magic_enum::enum_name(fmt))) {
InitBitmapBuffers(fmt, w, h, mips);
InitTextureObjs();
InitTextureObjs(false);
}
CTexture::CTexture(CInputStream& in, EAutoMipmap automip, EBlackKey blackKey) {
x64_frameAllocated = sCurrentFrameCount;
x0_fmt = ETexelFormat(in.ReadLong());
x4_w = in.ReadShort();
x6_h = in.ReadShort();
x8_mips = in.ReadLong();
CTexture::CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip, EBlackKey blackKey)
: x0_fmt(ETexelFormat(in.ReadLong()))
, x4_w(in.ReadShort())
, x6_h(in.ReadShort())
, x8_mips(in.ReadLong())
, x64_frameAllocated(sCurrentFrameCount)
, m_label(fmt::format(FMT_STRING("{} ({})"), label, magic_enum::enum_name(x0_fmt))) {
bool hasPalette = (x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2);
if (hasPalette) {
x10_graphicsPalette = std::make_unique<CGraphicsPalette>(in);
@ -128,10 +129,10 @@ CTexture::CTexture(CInputStream& in, EAutoMipmap automip, EBlackKey blackKey) {
}
}
InitTextureObjs();
InitTextureObjs(true);
}
void* CTexture::Lock() {
u8* CTexture::Lock() {
xa_24_locked = true;
return GetBitMapData(0);
}
@ -141,7 +142,8 @@ void CTexture::UnLock() {
CountMemory();
// DCFlushRange(x44_aramToken.GetMRAMSafe(), ROUND_UP_32(xc_memoryAllocated));
}
void CTexture::Load(GX::TexMapID id, CTexture::EClampMode clamp) {
void CTexture::Load(GX::TexMapID id, EClampMode clamp) {
if (sLoadedTextures[id] != this || xa_29_canLoadObj) {
auto* image_ptr = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get();
CountMemory();
@ -161,8 +163,8 @@ void CTexture::Load(GX::TexMapID id, CTexture::EClampMode clamp) {
x64_frameAllocated = sCurrentFrameCount;
}
}
void CTexture::LoadMipLevel(s32 mip, GX::TexMapID id, CTexture::EClampMode clamp) {
void CTexture::LoadMipLevel(s32 mip, GX::TexMapID id, EClampMode clamp) {
auto image_ptr = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get();
u32 width = x4_w;
u32 height = x6_h;
@ -196,7 +198,7 @@ void CTexture::MakeSwappable() {
xa_27_noSwap = false;
}
const void* CTexture::GetConstBitMapData(s32 mip) const {
const u8* CTexture::GetConstBitMapData(s32 mip) const {
u32 buffOffset = 0;
if (x8_mips > 0) {
for (u32 i = 0; i < x8_mips; ++i) {
@ -206,9 +208,9 @@ const void* CTexture::GetConstBitMapData(s32 mip) const {
return x44_aramToken_x4_buff.get() + buffOffset; /* x44_aramToken.GetMRAMSafe() + buffOffset*/
}
void* CTexture::GetBitMapData(s32 mip) const { return const_cast<void*>(GetConstBitMapData(mip)); }
u8* CTexture::GetBitMapData(s32 mip) const { return const_cast<u8*>(GetConstBitMapData(mip)); }
void CTexture::InitBitmapBuffers(ETexelFormat fmt, s16 width, s16 height, s32 mips) {
void CTexture::InitBitmapBuffers(ETexelFormat fmt, u16 width, u16 height, s32 mips) {
switch (fmt) {
case ETexelFormat::I4:
x18_gxFormat = GX::TF_I4;
@ -252,11 +254,12 @@ void CTexture::InitBitmapBuffers(ETexelFormat fmt, s16 width, s16 height, s32 mi
: x18_gxFormat;
xc_memoryAllocated = GXGetTexBufferSize(width, height, format, mips > 1, mips > 1 ? 11 : 0);
x44_aramToken_x4_buff.reset(new u8[xc_memoryAllocated]);
x44_aramToken_x4_buff = std::make_unique<u8[]>(xc_memoryAllocated);
/*x44_aramToken.PostConstruct(buf, xc_memoryAllocated, 1);*/
CountMemory();
}
void CTexture::InitTextureObjs() {
void CTexture::InitTextureObjs(bool write) {
xa_26_isPowerOfTwo = zeus::floorPowerOfTwo(x4_w) == x4_w && zeus::floorPowerOfTwo(x6_h) == x6_h;
if (!xa_26_isPowerOfTwo) {
@ -267,12 +270,17 @@ void CTexture::InitTextureObjs() {
if (IsCITexture()) {
// GXInitTexObjCI(x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat, u32(x40_clampMode),
// u32(x40_clampMode), x8_mips > 1, 0);
// TODO
} else {
// GXInitTexObj(x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat, u32(x40_clampMode),
// u32(x40_clampMode), x8_mips > 1);
// GXInitTexObjLOD(x20_texObj, x8_mips > 1 ? GX_LIN_MIP_LIN : GX_LINEAR, 0.f, static_cast<float>(x8_mips) - 1.f,
// 0.f,
// false, false, x8_mips > 1 ? GX_ANISO_4 : GX_ANISO_1);
x20_texObj = aurora::gfx::new_dynamic_texture_2d(x4_w, x6_h, x8_mips, x0_fmt, m_label);
if (write) {
aurora::gfx::write_texture(x20_texObj, {x44_aramToken_x4_buff.get(), xc_memoryAllocated});
}
}
xa_29_canLoadObj = true;
}
@ -325,12 +333,11 @@ bool CTexture::sMangleMips = false;
u32 CTexture::sCurrentFrameCount = 0;
u32 CTexture::sTotalAllocatedMemory = 0;
void CTexture::InvalidateTexMap(GX::TexMapID id) {
sLoadedTextures[id] = nullptr;
}
void CTexture::InvalidateTexMap(GX::TexMapID id) { sLoadedTextures[id] = nullptr; }
CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
CObjectReference* selfRef) {
return TToken<CTexture>::GetIObjObjectFor(std::make_unique<CTexture>(in));
const auto label = fmt::format("{} {}", tag.type, tag.id);
return TToken<CTexture>::GetIObjObjectFor(std::make_unique<CTexture>(in, label));
}
} // namespace metaforce::WIP
} // namespace metaforce

View File

@ -1,19 +1,13 @@
#pragma once
#include <memory>
#include <string>
#include "Runtime/CFactoryMgr.hpp"
#include "Runtime/GCNTypes.hpp"
#include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/IObj.hpp"
#include "Runtime/Streams/IOStreams.hpp"
#include "Runtime/Graphics/CGraphicsPalette.hpp"
#include "Runtime/Graphics/GX.hpp"
#include "Runtime/IObj.hpp"
#include "Runtime/Streams/CInputStream.hpp"
namespace metaforce {
class CVParamTransfer;
class CTextureInfo;
class CTexture {
class CDumpedBitmapDataReloader {
int x0_;
@ -26,12 +20,13 @@ class CTexture {
};
public:
enum class EClampMode {
Clamp,
Repeat,
Mirror,
enum class EAutoMipmap {
Zero,
One,
};
enum class EBlackKey { Zero, One };
enum class EFontType {
None = -1,
OneLayer = 0, /* Fill bit0 */
@ -43,74 +38,77 @@ public:
};
private:
static bool sMangleMips;
static u32 sCurrentFrameCount;
ETexelFormat x0_fmt;
u16 x4_w;
u16 x6_h;
u8 x8_mips;
u8 x9_bitsPerPixel;
u32 xc_memoryAllocated{};
static u32 sTotalAllocatedMemory;
ETexelFormat x0_fmt = ETexelFormat::Invalid;
u16 x4_w = 0;
u16 x6_h = 0;
u8 x8_mips = 0;
u8 x9_bitsPerPixel = 0;
bool xa_24_locked : 1 = false;
bool xa_25_canLoadPalette : 1 = false;
bool xa_26_isPowerOfTwo : 1 = false;
bool xa_27_noSwap : 1 = true;
bool xa_28_counted : 1 = false;
bool xa_29_canLoadObj : 1 = false;
u32 xc_memoryAllocated = 0;
std::unique_ptr<CGraphicsPalette> x10_graphicsPalette;
std::unique_ptr<CDumpedBitmapDataReloader> x14_bitmapReloader;
u32 x18_gxFormat{};
u32 x1c_gxCIFormat{};
/* GXTexObj x20_texObj */
u32 x18_gxFormat = GX::TF_RGB565;
u32 x1c_gxCIFormat = GX::TF_C8;
aurora::gfx::TextureHandle x20_texObj; // was GXTexObj
EClampMode x40_clampMode = EClampMode::Repeat;
/* CARAMToken x44_aramToken */
std::unique_ptr<u8[]> x44_aramToken_x4_buff; // was CARAMToken
u32 x64_frameAllocated{};
aurora::gfx::TextureHandle m_tex;
aurora::gfx::TextureHandle m_paletteTex;
std::unique_ptr<u8[]> m_otex;
EFontType m_ftype = EFontType::None;
const CTextureInfo* m_textureInfo{};
// Metaforce additions
std::string m_label;
size_t ComputeMippedTexelCount() const;
size_t ComputeMippedBlockCountDXT1() const;
void BuildI4FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildI8FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildIA4FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildIA8FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildC4FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildC8FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildC14X2FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildRGB565FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildRGB5A3FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildRGBA8FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildDXT1FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildRGBA8(const void* data, size_t length, aurora::zstring_view label);
void BuildC8(const void* data, size_t length, aurora::zstring_view label);
void BuildC8Font(const void* data, EFontType ftype, aurora::zstring_view label);
void BuildDXT1(const void* data, size_t length, aurora::zstring_view label);
void BuildDXT3(const void* data, size_t length, aurora::zstring_view label);
void InitBitmapBuffers(ETexelFormat fmt, s16 width, s16 height, s32 mips);
void InitTextureObjs();
void InitBitmapBuffers(ETexelFormat fmt, u16 width, u16 height, s32 mips);
void InitTextureObjs(bool write); // write param is added
void CountMemory();
void UncountMemory();
void MangleMipmap(u32 mip);
static u32 TexelFormatBitsPerPixel(ETexelFormat fmt);
public:
CTexture(ETexelFormat, s16, s16, s32);
CTexture(std::unique_ptr<u8[]>&& in, u32 length, bool otex, const CTextureInfo* inf, CAssetId id);
[[nodiscard]] ETexelFormat GetTexelFormat() const { return x0_fmt; }
[[nodiscard]] ETexelFormat GetMemoryCardTexelFormat() const {
return x0_fmt == ETexelFormat::C8PC ? ETexelFormat::C8 : ETexelFormat::RGB5A3;
}
// Label parameters are new for Metaforce
CTexture(ETexelFormat fmt, u16 w, u16 h, s32 mips, std::string_view label);
CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip = EAutoMipmap::Zero,
EBlackKey blackKey = EBlackKey::Zero);
[[nodiscard]] ETexelFormat GetTextureFormat() const { return x0_fmt; }
[[nodiscard]] u16 GetWidth() const { return x4_w; }
[[nodiscard]] u16 GetHeight() const { return x6_h; }
[[nodiscard]] u8 GetNumMips() const { return x8_mips; }
[[nodiscard]] u8 GetBitsPerPixel() const { return x9_bitsPerPixel; }
void Load(int slot, EClampMode clamp) const;
[[nodiscard]] const aurora::gfx::TextureHandle& GetTexture() const { return m_tex; }
[[nodiscard]] const aurora::gfx::TextureHandle& GetPaletteTexture() const { return m_paletteTex; }
std::unique_ptr<u8[]> BuildMemoryCardTex(u32& sizeOut, ETexelFormat& fmtOut, std::unique_ptr<u8[]>& paletteOut) const;
const aurora::gfx::TextureHandle& GetFontTexture(EFontType tp);
[[nodiscard]] u8 GetNumberOfMipMaps() const { return x8_mips; }
[[nodiscard]] u32 GetBitDepth() const { return x9_bitsPerPixel; }
[[nodiscard]] u32 GetMemoryAllocated() const { return xc_memoryAllocated; }
[[nodiscard]] const std::unique_ptr<CGraphicsPalette>& GetPalette() const { return x10_graphicsPalette; }
[[nodiscard]] bool HasPalette() const { return x10_graphicsPalette != nullptr; }
[[nodiscard]] u8* Lock();
void UnLock();
void Load(GX::TexMapID id, EClampMode clamp);
void LoadMipLevel(s32 mip, GX::TexMapID id, EClampMode clamp);
// void UnloadBitmapData(u32) const;
// void TryReloadBitmapData(CResFactory&) const;
// void LoadToMRAM() const;
// void LoadToARAM() const;
// bool IsARAMTransferInProgress() const { return false; }
void MakeSwappable();
[[nodiscard]] const CTextureInfo* GetTextureInfo() const { return m_textureInfo; }
[[nodiscard]] const u8* GetConstBitMapData(s32 mip) const;
[[nodiscard]] u8* GetBitMapData(s32 mip) const;
[[nodiscard]] bool IsCITexture() const {
return x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2;
}
static u32 TexelFormatBitsPerPixel(ETexelFormat fmt);
static void InvalidateTexMap(GX::TexMapID id);
static void SetMangleMips(bool b) { sMangleMips = b; }
static void SetCurrentFrameCount(u32 frameCount) { sCurrentFrameCount = frameCount; }
};
CFactoryFnReturn FTextureFactory(const metaforce::SObjectTag& tag, std::unique_ptr<u8[]>&& in, u32 len,
const metaforce::CVParamTransfer& vparms, CObjectReference* selfRef);
CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
CObjectReference* selfRef);
} // namespace metaforce

View File

@ -0,0 +1,116 @@
#pragma once
#include <memory>
#include <string>
#include "Runtime/CFactoryMgr.hpp"
#include "Runtime/GCNTypes.hpp"
#include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/IObj.hpp"
#include "Runtime/Streams/IOStreams.hpp"
#include "Runtime/Graphics/CGraphicsPalette.hpp"
namespace metaforce {
class CVParamTransfer;
class CTextureInfo;
class CTexture {
class CDumpedBitmapDataReloader {
int x0_;
u32 x4_;
int x8_;
u32 xc_;
bool x10_;
int x14_;
void* x18_;
};
public:
enum class EClampMode {
Clamp,
Repeat,
Mirror,
};
enum class EFontType {
None = -1,
OneLayer = 0, /* Fill bit0 */
OneLayerOutline = 1, /* Fill bit0, Outline bit1 */
FourLayers = 2,
TwoLayersOutlines = 3, /* Fill bit0/2, Outline bit1/3 */
TwoLayers = 4, /* Fill bit0/1 and copied to bit2/3 */
TwoLayersOutlines2 = 8 /* Fill bit2/3, Outline bit0/1 */
};
private:
static u32 sCurrentFrameCount;
ETexelFormat x0_fmt;
u16 x4_w;
u16 x6_h;
u8 x8_mips;
u8 x9_bitsPerPixel;
u32 xc_memoryAllocated{};
std::unique_ptr<CGraphicsPalette> x10_graphicsPalette;
std::unique_ptr<CDumpedBitmapDataReloader> x14_bitmapReloader;
u32 x18_gxFormat{};
u32 x1c_gxCIFormat{};
/* GXTexObj x20_texObj */
EClampMode x40_clampMode = EClampMode::Repeat;
/* CARAMToken x44_aramToken */
u32 x64_frameAllocated{};
aurora::gfx::TextureHandle m_tex;
aurora::gfx::TextureHandle m_paletteTex;
std::unique_ptr<u8[]> m_otex;
EFontType m_ftype = EFontType::None;
const CTextureInfo* m_textureInfo{};
size_t ComputeMippedTexelCount() const;
size_t ComputeMippedBlockCountDXT1() const;
void BuildI4FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildI8FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildIA4FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildIA8FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildC4FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildC8FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildC14X2FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildRGB565FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildRGB5A3FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildRGBA8FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildDXT1FromGCN(CInputStream& in, aurora::zstring_view label);
void BuildRGBA8(const void* data, size_t length, aurora::zstring_view label);
void BuildC8(const void* data, size_t length, aurora::zstring_view label);
void BuildC8Font(const void* data, EFontType ftype, aurora::zstring_view label);
void BuildDXT1(const void* data, size_t length, aurora::zstring_view label);
void BuildDXT3(const void* data, size_t length, aurora::zstring_view label);
void InitBitmapBuffers(ETexelFormat fmt, s16 width, s16 height, s32 mips);
void InitTextureObjs();
public:
CTexture(ETexelFormat, s16, s16, s32);
CTexture(std::unique_ptr<u8[]>&& in, u32 length, bool otex, const CTextureInfo* inf, CAssetId id);
[[nodiscard]] ETexelFormat GetTexelFormat() const { return x0_fmt; }
[[nodiscard]] ETexelFormat GetMemoryCardTexelFormat() const {
return x0_fmt == ETexelFormat::C8PC ? ETexelFormat::C8 : ETexelFormat::RGB5A3;
}
[[nodiscard]] u16 GetWidth() const { return x4_w; }
[[nodiscard]] u16 GetHeight() const { return x6_h; }
[[nodiscard]] u8 GetNumMips() const { return x8_mips; }
[[nodiscard]] u8 GetBitsPerPixel() const { return x9_bitsPerPixel; }
void Load(int slot, EClampMode clamp) const;
[[nodiscard]] const aurora::gfx::TextureHandle& GetTexture() const { return m_tex; }
[[nodiscard]] const aurora::gfx::TextureHandle& GetPaletteTexture() const { return m_paletteTex; }
std::unique_ptr<u8[]> BuildMemoryCardTex(u32& sizeOut, ETexelFormat& fmtOut, std::unique_ptr<u8[]>& paletteOut) const;
const aurora::gfx::TextureHandle& GetFontTexture(EFontType tp);
[[nodiscard]] const CTextureInfo* GetTextureInfo() const { return m_textureInfo; }
static u32 TexelFormatBitsPerPixel(ETexelFormat fmt);
static void SetCurrentFrameCount(u32 frameCount) { sCurrentFrameCount = frameCount; }
};
CFactoryFnReturn FTextureFactory(const metaforce::SObjectTag& tag, std::unique_ptr<u8[]>&& in, u32 len,
const metaforce::CVParamTransfer& vparms, CObjectReference* selfRef);
} // namespace metaforce

View File

@ -1,105 +0,0 @@
#pragma once
#include "Runtime/CFactoryMgr.hpp"
#include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/Graphics/CGraphicsPalette.hpp"
#include "Runtime/IObj.hpp"
#include "Runtime/Streams/CInputStream.hpp"
#include "Runtime/Graphics/GX.hpp"
namespace metaforce::WIP {
class CTexture {
class CDumpedBitmapDataReloader {
int x0_;
u32 x4_;
int x8_;
u32 xc_;
bool x10_;
int x14_;
void* x18_;
};
public:
enum class EClampMode {
Clamp,
Repeat,
Mirror,
};
enum class EAutoMipmap {
Zero,
One,
};
enum class EBlackKey { Zero, One };
private:
static bool sMangleMips;
static u32 sCurrentFrameCount;
static u32 sTotalAllocatedMemory;
ETexelFormat x0_fmt = ETexelFormat::Invalid;
u16 x4_w = 0;
u16 x6_h = 0;
u8 x8_mips = 0;
u8 x9_bitsPerPixel = 0;
bool xa_24_locked : 1 = false;
bool xa_25_canLoadPalette : 1 = false;
bool xa_26_isPowerOfTwo : 1 = false;
bool xa_27_noSwap : 1 = true;
bool xa_28_counted : 1 = false;
bool xa_29_canLoadObj : 1 = false;
u32 xc_memoryAllocated = 0;
std::unique_ptr<CGraphicsPalette> x10_graphicsPalette;
std::unique_ptr<CDumpedBitmapDataReloader> x14_bitmapReloader;
u32 x18_gxFormat = GX::TF_RGB565;
u32 x1c_gxCIFormat = GX::TF_C8;
/* GXTexObj x20_texObj */
EClampMode x40_clampMode = EClampMode::Repeat;
/* CARAMToken x44_aramToken */
std::unique_ptr<u8[]> x44_aramToken_x4_buff;
u32 x64_frameAllocated{};
void InitBitmapBuffers(ETexelFormat fmt, s16 width, s16 height, s32 mips);
void InitTextureObjs();
void CountMemory();
void UncountMemory();
void MangleMipmap(u32 mip);
static u32 TexelFormatBitsPerPixel(ETexelFormat fmt);
public:
CTexture(ETexelFormat, s16, s16, s32);
CTexture(CInputStream& in, EAutoMipmap automip = EAutoMipmap::Zero, EBlackKey blackKey = EBlackKey::Zero);
[[nodiscard]] ETexelFormat GetTextureFormat() const { return x0_fmt; }
[[nodiscard]] s16 GetWidth(s32 mip) const { return x4_w; }
[[nodiscard]] s16 GetHeight(s32 mip) const { return x6_h; }
[[nodiscard]] u8 GetNumberOfMipMaps() const { return x8_mips; }
[[nodiscard]] u32 GetBitDepth() const { return x9_bitsPerPixel; }
[[nodiscard]] u32 GetMemoryAllocated() const { return xc_memoryAllocated; }
[[nodiscard]] const std::unique_ptr<CGraphicsPalette>& GetPalette() const { return x10_graphicsPalette; }
[[nodiscard]] bool HasPalette() const { return x10_graphicsPalette != nullptr; }
[[nodiscard]] void* Lock();
void UnLock();
void Load(GX::TexMapID id, EClampMode clamp);
void LoadMipLevel(s32 mip, GX::TexMapID id, EClampMode clamp);
// void UnloadBitmapData(u32) const;
// void TryReloadBitmapData(CResFactory&) const;
// void LoadToMRAM() const;
// void LoadToARAM() const;
// bool IsARAMTransferInProgress() const { return false; }
void MakeSwappable();
[[nodiscard]] const void* GetConstBitMapData(s32 mip) const;
[[nodiscard]] void* GetBitMapData(s32 mip) const;
[[nodiscard]] bool IsCITexture() const {
return x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2;
}
static void InvalidateTexMap(GX::TexMapID id);
static void SetMangleMips(bool b) { sMangleMips = b; }
static void SetCurrentFrameCount(u32 frameCount) { sCurrentFrameCount = frameCount; }
};
CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
CObjectReference* selfRef);
} // namespace metaforce::WIP

View File

@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
#include <cstddef>
namespace GX {
enum AttrType { NONE, DIRECT, INDEX8, INDEX16 };

View File

@ -36,7 +36,7 @@ void CSpaceWarpFilter::GenerateWarpRampTex() {
}
}
m_warpTex = aurora::gfx::new_static_texture_2d(
WARP_RAMP_RES + 1, WARP_RAMP_RES + 1, 1, aurora::gfx::TextureFormat::R8,
WARP_RAMP_RES + 1, WARP_RAMP_RES + 1, 1, ETexelFormat::RGBA8PC,
{reinterpret_cast<const uint8_t*>(data.data()), (WARP_RAMP_RES + 1) * (WARP_RAMP_RES + 1) * 4}, "Warp Ramp");
}

View File

@ -201,7 +201,7 @@ CTexturedQuadFilter::CTexturedQuadFilter(EFilterType type, const aurora::gfx::Te
}
CTexturedQuadFilter::CTexturedQuadFilter(EFilterType type, TLockedToken<CTexture> tex, ERglEnum ztest)
: CTexturedQuadFilter(type, (tex ? tex->GetTexture() : aurora::gfx::TextureHandle{}), ztest) {
: CTexturedQuadFilter(type, aurora::gfx::TextureHandle{}, ztest) {
m_flipRect = true; // TODO?
m_tex = tex;
}
@ -339,7 +339,7 @@ CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, const auror
}
CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, TLockedToken<CTexture> tex)
: CTexturedQuadFilterAlpha(type, (tex ? tex->GetTexture() : aurora::gfx::TextureHandle{})) {
: CTexturedQuadFilterAlpha(type, aurora::gfx::TextureHandle{}) {
m_tex = tex;
}

View File

@ -19,7 +19,7 @@ void CXRayBlurFilter::Shutdown() {
// s_Pipeline.reset();
}
CXRayBlurFilter::CXRayBlurFilter(TLockedToken<CTexture>& tex) : m_paletteTex(tex), m_booTex(tex->GetPaletteTexture()) {
CXRayBlurFilter::CXRayBlurFilter(TLockedToken<CTexture>& tex) : m_paletteTex(tex) { // , m_booTex(tex->GetPaletteTexture())
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
// struct Vert {
// zeus::CVector2f m_pos;

View File

@ -83,18 +83,18 @@ void CAuiImagePane::DoDrawImagePane(const zeus::CColor& color, const CTexture& t
bool zTest = xac_drawFlags == EGuiModelDrawFlags::Shadeless || xac_drawFlags == EGuiModelDrawFlags::Opaque;
if (noBlur) {
aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, 0);
// aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
// aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, 0);
// quad.drawVerts(useColor, verts);
} else if ((x14c_deResFactor == 0.f && alpha == 1.f) || tex.GetNumMips() == 1) {
aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, 0);
} else if ((x14c_deResFactor == 0.f && alpha == 1.f) || tex.GetNumberOfMipMaps() == 1) {
// aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
// aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, 0);
} else {
const float tmp = (1.f - x14c_deResFactor) * alpha;
const float tmp3 = 1.f - tmp * tmp * tmp;
const float mip = tmp3 * static_cast<float>(tex.GetNumMips() - 1);
aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, mip);
const float mip = tmp3 * static_cast<float>(tex.GetNumberOfMipMaps() - 1);
// aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
// aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, mip);
}
}

View File

@ -148,7 +148,7 @@ public:
const char16_t* str, int len) const;
const CGlyph* GetGlyph(char16_t chr) const { return InternalGetGlyph(chr); }
void GetSize(const CDrawStringOptions& opts, int& width, int& height, const char16_t* str, int len) const;
const aurora::gfx::TextureHandle& GetTexture() { return x80_texture->GetFontTexture(x2c_mode); }
CTexture& GetTexture() { return *x80_texture; }
bool IsFinishedLoading() const;
};

View File

@ -66,29 +66,42 @@ void CSplashScreen::Draw() {
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
g_Renderer->SetModelMatrix({});
CGraphics::SetViewPointMatrix({});
// CGraphics::SetTevOp(Stage0, ?);
// CGraphics::SetTevOp(Stage1, skPassThru);
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
g_Renderer->SetBlendMode_AlphaBlended();
const auto& tex = *x28_texture.GetObj();
auto& tex = *x28_texture.GetObj();
const auto width = tex.GetWidth();
const auto height = tex.GetHeight();
tex.Load(GX::TEXMAP0, EClampMode::Clamp);
if (x14_which == ESplashScreen::Nintendo || x14_which == ESplashScreen::Retro) {
const auto x = static_cast<float>(133 - (width - 376) / 2);
const auto y = static_cast<float>(170 - (height - 104) / 2);
CGraphics::SetOrtho(-10.f, 650.f, -5.5f, 484.5f, -1.f, 1.f);
CGraphics::SetCullMode(ERglCullMode::None);
// TODO
CGraphics::StreamBegin(GX::TRIANGLESTRIP);
CGraphics::StreamColor(color);
CGraphics::StreamTexcoord(0.f, 0.f);
CGraphics::StreamVertex({x, 0.f, y + static_cast<float>(height)});
CGraphics::StreamTexcoord(0.f, 1.f);
CGraphics::StreamVertex({x, 0.f, y});
CGraphics::StreamTexcoord(1.f, 0.f);
CGraphics::StreamVertex({x + static_cast<float>(width), 0.f, y + static_cast<float>(height)});
CGraphics::StreamTexcoord(1.f, 1.f);
CGraphics::StreamVertex({x + static_cast<float>(width), 0.f, y});
CGraphics::StreamEnd();
CGraphics::SetCullMode(ERglCullMode::Front);
} else {
// TODO
// CGraphics::Render2D();
}
zeus::CRectangle rect;
rect.size.x() = width / (480.f * CGraphics::GetViewportAspect());
rect.size.y() = height / 480.f;
rect.position.x() = 0.5f - rect.size.x() / 2.f;
rect.position.y() = 0.5f - rect.size.y() / 2.f;
aurora::gfx::queue_textured_quad(aurora::gfx::CameraFilterType::Blend, tex.GetTexture(),
aurora::gfx::ZComp::Always, false, color, 1.f, rect, 0.f);
// zeus::CRectangle rect;
// rect.size.x() = width / (480.f * CGraphics::GetViewportAspect());
// rect.size.y() = height / 480.f;
// rect.position.x() = 0.5f - rect.size.x() / 2.f;
// rect.position.y() = 0.5f - rect.size.y() / 2.f;
// aurora::gfx::queue_textured_quad(aurora::gfx::CameraFilterType::Blend, tex.GetTexture(),
// aurora::gfx::ZComp::Always, false, color, 1.f, rect, 0.f);
// Progressive scan options omitted
}

View File

@ -200,20 +200,9 @@ CIOWin::EMessageReturn CCredits::ProcessUserInput(const CFinalInput& input) {
}
void CCredits::DrawVideo() {
/* Correct movie aspect ratio */
float hPad, vPad;
if (CGraphics::GetViewportAspect() >= 1.78f) {
hPad = 1.78f / CGraphics::GetViewportAspect();
vPad = 1.78f / 1.33f;
} else {
hPad = 1.f;
vPad = CGraphics::GetViewportAspect() / 1.33f;
}
if (x28_ && x28_->GetIsFullyCached()) {
if (x28_) {
/* Render movie */
x28_->SetFrame(hPad, vPad);
x28_->DrawFrame();
x28_->Draw();
if (x5c_27_ || x5c_28_) {
float alpha = x58_ / g_tweakGui->x310_;
if (x5c_27_) {

View File

@ -113,8 +113,8 @@ void CFrontEndUI::PlayAdvanceSfx() {
CSfxManager::SfxStart(SFXfnt_advance_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
}
CFrontEndUI::SNewFileSelectFrame::SNewFileSelectFrame(CSaveGameScreen* sui, u32 rnd, CFrontEndUITouchBar& touchBar)
: x0_rnd(rnd), x4_saveUI(sui), m_touchBar(touchBar) {
CFrontEndUI::SNewFileSelectFrame::SNewFileSelectFrame(CSaveGameScreen* sui, u32 rnd)
: x0_rnd(rnd), x4_saveUI(sui) {
x10_frme = g_SimplePool->GetObj("FRME_NewFileSelect");
}
@ -219,7 +219,7 @@ void CFrontEndUI::SNewFileSelectFrame::Update(float dt) {
}
CFrontEndUI::SNewFileSelectFrame::EAction
CFrontEndUI::SNewFileSelectFrame::ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction) {
CFrontEndUI::SNewFileSelectFrame::ProcessUserInput(const CFinalInput& input) {
xc_action = EAction::None;
if (x8_subMenu != ESubMenu::EraseGamePopup)
@ -233,46 +233,6 @@ CFrontEndUI::SNewFileSelectFrame::ProcessUserInput(const CFinalInput& input, CFr
if (x10c_saveReady) {
x1c_loadedFrame->ProcessUserInput(input);
if (x8_subMenu == ESubMenu::Root || x8_subMenu == ESubMenu::EraseGame) {
if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::FileSelect)
HandleActiveChange(x20_tablegroup_fileselect);
if (tbAction >= CFrontEndUITouchBar::EAction::FileA && tbAction <= CFrontEndUITouchBar::EAction::ImageGallery) {
x20_tablegroup_fileselect->SetUserSelection(int(tbAction) - int(CFrontEndUITouchBar::EAction::FileA));
HandleActiveChange(x20_tablegroup_fileselect);
DoFileMenuAdvance(x20_tablegroup_fileselect);
} else if (tbAction == CFrontEndUITouchBar::EAction::Back) {
DoFileMenuCancel(x20_tablegroup_fileselect);
}
} else if (x8_subMenu == ESubMenu::EraseGamePopup) {
if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::EraseBack)
HandleActiveChange(x40_tablegroup_popup);
if (tbAction != CFrontEndUITouchBar::EAction::None) {
if (tbAction == CFrontEndUITouchBar::EAction::Confirm)
x40_tablegroup_popup->SetUserSelection(1);
else
x40_tablegroup_popup->SetUserSelection(0);
HandleActiveChange(x40_tablegroup_popup);
DoPopupAdvance(x40_tablegroup_popup);
}
} else if (x8_subMenu == ESubMenu::NewGamePopup) {
if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::StartOptions)
HandleActiveChange(x40_tablegroup_popup);
if (tbAction == CFrontEndUITouchBar::EAction::Back) {
DoPopupCancel(x40_tablegroup_popup);
} else if (tbAction != CFrontEndUITouchBar::EAction::None) {
if (tbAction == CFrontEndUITouchBar::EAction::Options)
x40_tablegroup_popup->SetUserSelection(1);
else if (tbAction == CFrontEndUITouchBar::EAction::Start || tbAction == CFrontEndUITouchBar::EAction::Hard)
x40_tablegroup_popup->SetUserSelection(0);
else if (tbAction == CFrontEndUITouchBar::EAction::Normal)
x40_tablegroup_popup->SetUserSelection(2);
HandleActiveChange(x40_tablegroup_popup);
DoPopupAdvance(x40_tablegroup_popup);
}
}
}
if (x10d_needsEraseToggle) {
@ -308,25 +268,6 @@ void CFrontEndUI::SNewFileSelectFrame::HandleActiveChange(CGuiTableGroup* active
if (active == x20_tablegroup_fileselect) {
x24_model_erase->SetLocalTransform(zeus::CTransform::Translate(
zeus::CVector3f{0.f, 0.f, active->GetUserSelection() * x104_rowPitch} + xf8_model_erase_position));
/* Set Touch Bar contents here */
std::array<CFrontEndUITouchBar::SFileSelectDetail, 3> tbDetails{};
for (size_t i = 0; i < tbDetails.size(); ++i) {
if (const CGameState::GameFileStateInfo* data = x4_saveUI->GetGameData(int(i))) {
tbDetails[i].state =
data->x20_hardMode ? CFrontEndUITouchBar::EFileState::Hard : CFrontEndUITouchBar::EFileState::Normal;
tbDetails[i].percent = data->x18_itemPercent;
}
}
m_touchBar.SetFileSelectPhase(tbDetails.data(), x8_subMenu == ESubMenu::EraseGame,
CSlideShow::SlideShowGalleryFlags());
} else if (active == x40_tablegroup_popup) {
if (x8_subMenu == ESubMenu::EraseGamePopup)
m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::EraseBack);
else if (x8_subMenu == ESubMenu::NewGamePopup)
m_touchBar.SetStartOptionsPhase(g_GameState->SystemOptions().GetPlayerBeatNormalMode());
else
m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::None);
}
if (x8_subMenu == ESubMenu::Root || x8_subMenu == ESubMenu::NewGamePopup)
@ -682,7 +623,6 @@ void CFrontEndUI::SNewFileSelectFrame::DoFileMenuAdvance(CGuiTableGroup* caller)
}
} else {
if (x4_saveUI->GetGameData(userSel)) {
m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::None);
x4_saveUI->StartGame(userSel);
} else
x10e_needsNewToggle = true;
@ -712,7 +652,7 @@ void CFrontEndUI::SNewFileSelectFrame::StartTextAnimating(CGuiTextPane* text, st
text->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, chRate);
}
CFrontEndUI::SFusionBonusFrame::SFusionBonusFrame(CFrontEndUITouchBar& touchBar) : m_touchBar(touchBar) {
CFrontEndUI::SFusionBonusFrame::SFusionBonusFrame() {
if (!g_Main->IsTrilogy()) {
x4_gbaSupport = std::make_unique<CGBASupport>();
xc_gbaScreen = g_SimplePool->GetObj("FRME_GBAScreen");
@ -830,8 +770,7 @@ void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::SetUIText(EUIType tp) {
}
CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EAction
CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::ProcessUserInput(const CFinalInput& input, bool linkInProgress,
CFrontEndUITouchBar::EAction tbAction) {
CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::ProcessUserInput(const CFinalInput& input, bool linkInProgress) {
if (linkInProgress != x40_linkInProgress) {
x40_linkInProgress = linkInProgress;
SetUIText(x0_uiType);
@ -845,12 +784,10 @@ CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::ProcessUserInput(const CFinalInpu
case EUIType::LinkFailed:
case EUIType::LinkCompleteOrLinking:
case EUIType::TurnOffGBA:
if (input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary) ||
tbAction == CFrontEndUITouchBar::EAction::Confirm) {
if (input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) {
PlayAdvanceSfx();
SetUIText(NextLinkUI[size_t(x0_uiType)]);
} else if (input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc) ||
tbAction == CFrontEndUITouchBar::EAction::Back) {
} else if (input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc)) {
const EUIType prevUi = PrevLinkUI[size_t(x0_uiType)];
if (prevUi == EUIType::Empty) {
break;
@ -1026,8 +963,7 @@ void CFrontEndUI::SFusionBonusFrame::Update(float dt, CSaveGameScreen* saveUI) {
}
CFrontEndUI::SFusionBonusFrame::EAction
CFrontEndUI::SFusionBonusFrame::ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui,
CFrontEndUITouchBar::EAction tbAction) {
CFrontEndUI::SFusionBonusFrame::ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui) {
x8_action = EAction::None;
if (sui)
@ -1035,10 +971,7 @@ CFrontEndUI::SFusionBonusFrame::ProcessUserInput(const CFinalInput& input, CSave
if (x38_lastDoDraw) {
if (x0_gbaLinkFrame) {
if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::ProceedBack)
m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::ProceedBack);
SGBALinkFrame::EAction action = x0_gbaLinkFrame->ProcessUserInput(input, sui, tbAction);
SGBALinkFrame::EAction action = x0_gbaLinkFrame->ProcessUserInput(input, sui);
if (action != SGBALinkFrame::EAction::None) {
x0_gbaLinkFrame.reset();
if (action == SGBALinkFrame::EAction::Complete) {
@ -1054,45 +987,7 @@ CFrontEndUI::SFusionBonusFrame::ProcessUserInput(const CFinalInput& input, CSave
useInput.x2d_b28_PA = true;
m_gbaOverride = true;
}
bool showFusionSuit = (g_GameState->SystemOptions().GetPlayerLinkedFusion() &&
g_GameState->SystemOptions().GetPlayerBeatNormalMode()) ||
m_gbaOverride;
if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::FusionBonus) {
m_touchBar.SetFusionBonusPhase(showFusionSuit && g_GameState->SystemOptions().GetPlayerFusionSuitActive());
}
x24_loadedFrame->ProcessUserInput(useInput);
switch (tbAction) {
case CFrontEndUITouchBar::EAction::NESMetroid:
x28_tablegroup_options->SetUserSelection(0);
ResetCompletionFlags();
SetTableColors(x28_tablegroup_options);
DoAdvance(x28_tablegroup_options);
break;
case CFrontEndUITouchBar::EAction::FusionSuit:
x28_tablegroup_options->SetUserSelection(1);
ResetCompletionFlags();
SetTableColors(x28_tablegroup_options);
if (showFusionSuit) {
if (x2c_tablegroup_fusionsuit->GetUserSelection() == 1) {
x2c_tablegroup_fusionsuit->SetUserSelection(0);
DoSelectionChange(x2c_tablegroup_fusionsuit, 0);
} else {
x2c_tablegroup_fusionsuit->SetUserSelection(1);
DoSelectionChange(x2c_tablegroup_fusionsuit, 1);
}
} else {
DoAdvance(x28_tablegroup_options);
}
break;
case CFrontEndUITouchBar::EAction::Back:
DoCancel(x28_tablegroup_options);
break;
default:
break;
}
}
}
@ -1125,7 +1020,6 @@ void CFrontEndUI::SFusionBonusFrame::DoSelectionChange(CGuiTableGroup* caller, i
bool fusionActive = x2c_tablegroup_fusionsuit->GetUserSelection() == 1;
g_GameState->SystemOptions().SetPlayerFusionSuitActive(fusionActive);
g_GameState->GetPlayerState()->SetIsFusionEnabled(fusionActive);
m_touchBar.SetFusionBonusPhase(g_GameState->SystemOptions().GetPlayerFusionSuitActive());
}
SetTableColors(caller);
}
@ -1256,38 +1150,9 @@ void CFrontEndUI::SFrontEndFrame::Update(float dt) {
}
CFrontEndUI::SFrontEndFrame::EAction
CFrontEndUI::SFrontEndFrame::ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction) {
if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::NoCardSelect)
m_touchBar.SetNoCardSelectPhase(CSlideShow::SlideShowGalleryFlags());
CFrontEndUI::SFrontEndFrame::ProcessUserInput(const CFinalInput& input) {
x4_action = EAction::None;
x14_loadedFrme->ProcessUserInput(input);
switch (tbAction) {
case CFrontEndUITouchBar::EAction::Start:
x18_tablegroup_mainmenu->SetUserSelection(0);
HandleActiveChange(x18_tablegroup_mainmenu);
DoAdvance(x18_tablegroup_mainmenu);
break;
case CFrontEndUITouchBar::EAction::FusionBonus:
x18_tablegroup_mainmenu->SetUserSelection(1);
HandleActiveChange(x18_tablegroup_mainmenu);
DoAdvance(x18_tablegroup_mainmenu);
break;
case CFrontEndUITouchBar::EAction::Options:
x18_tablegroup_mainmenu->SetUserSelection(2);
HandleActiveChange(x18_tablegroup_mainmenu);
DoAdvance(x18_tablegroup_mainmenu);
break;
case CFrontEndUITouchBar::EAction::ImageGallery:
x18_tablegroup_mainmenu->SetUserSelection(3);
HandleActiveChange(x18_tablegroup_mainmenu);
DoAdvance(x18_tablegroup_mainmenu);
break;
default:
break;
}
return x4_action;
}
@ -1328,8 +1193,8 @@ void CFrontEndUI::SFrontEndFrame::DoAdvance(CGuiTableGroup* caller) {
}
}
CFrontEndUI::SFrontEndFrame::SFrontEndFrame(u32 rnd, CFrontEndUITouchBar& touchBar)
: x0_rnd(rnd), m_touchBar(touchBar) {
CFrontEndUI::SFrontEndFrame::SFrontEndFrame(u32 rnd)
: x0_rnd(rnd) {
x8_frme = g_SimplePool->GetObj("FRME_FrontEndPL");
}
@ -1501,7 +1366,6 @@ void CFrontEndUI::SOptionsFrontEndFrame::DoSliderChange(CGuiSliderGroup* caller,
const auto& optionCategory = GameOptionsRegistry[leftSel];
const SGameOption& option = optionCategory.second[rightSel];
CGameOptions::SetOption(option.option, caller->GetGurVal());
m_touchBarValueDirty = true;
}
}
@ -1531,7 +1395,6 @@ void CFrontEndUI::SOptionsFrontEndFrame::DoMenuSelectionChange(CGuiTableGroup* c
const auto& optionCategory = GameOptionsRegistry[leftSel];
const SGameOption& option = optionCategory.second[rightSel];
CGameOptions::SetOption(option.option, caller->GetUserSelection());
m_touchBarValueDirty = true;
CSfxManager::SfxStart(SFXfnt_enum_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
if (option.option == EGameOption::Rumble && caller->GetUserSelection() > 0) {
@ -1709,7 +1572,6 @@ bool CFrontEndUI::SOptionsFrontEndFrame::PumpLoad() {
return false;
x1c_loadedFrame = x4_frme.GetObj();
x20_loadedPauseStrg = x10_pauseScreen.GetObj();
m_touchBar = NewGameOptionsTouchBar();
FinishedLoading();
return true;
}
@ -1727,66 +1589,6 @@ bool CFrontEndUI::SOptionsFrontEndFrame::ProcessUserInput(const CFinalInput& inp
int leftSel = x24_tablegroup_leftmenu->GetUserSelection();
int rightSel = x28_tablegroup_rightmenu->GetUserSelection();
CGameOptions::TryRestoreDefaults(input, leftSel, rightSel, true, false);
CGameOptionsTouchBar::EAction tbAction = m_touchBar->PopAction();
if (x28_tablegroup_rightmenu->GetIsActive()) {
if (tbAction == CGameOptionsTouchBar::EAction::Advance && !m_touchBarInValue) {
int value;
m_touchBar->GetSelection(leftSel, rightSel, value);
x28_tablegroup_rightmenu->SetUserSelection(rightSel);
SetTableColors(x28_tablegroup_rightmenu);
HandleRightSelectionChange();
const auto& optionCategory = GameOptionsRegistry[leftSel];
const SGameOption& option = optionCategory.second[rightSel];
if (option.type != EOptionType::RestoreDefaults) {
m_touchBarInValue = true;
m_touchBarValueDirty = true;
} else {
CGameOptions::TryRestoreDefaults(input, leftSel, rightSel, true, true);
}
} else if (tbAction == CGameOptionsTouchBar::EAction::Back) {
if (m_touchBarInValue)
m_touchBarInValue = false;
else
DoMenuCancel(x28_tablegroup_rightmenu);
} else if (tbAction == CGameOptionsTouchBar::EAction::ValueChange) {
int value;
m_touchBar->GetSelection(leftSel, rightSel, value);
const auto& optionCategory = GameOptionsRegistry[leftSel];
const SGameOption& option = optionCategory.second[rightSel];
CGameOptions::SetOption(option.option, value);
if (option.type != EOptionType::Float)
m_touchBarValueDirty = true;
HandleRightSelectionChange();
} else {
if (m_touchBarInValue) {
if (m_touchBarValueDirty) {
const auto& optionCategory = GameOptionsRegistry[leftSel];
const SGameOption& option = optionCategory.second[rightSel];
int value = CGameOptions::GetOption(option.option);
m_touchBar->SetSelection(leftSel, rightSel, value);
m_touchBarValueDirty = false;
}
} else {
m_touchBar->SetSelection(leftSel, -1, -1);
}
}
} else {
if (tbAction == CGameOptionsTouchBar::EAction::Advance) {
int value;
m_touchBar->GetSelection(leftSel, rightSel, value);
x24_tablegroup_leftmenu->SetUserSelection(leftSel);
SetTableColors(x24_tablegroup_leftmenu);
SetRightUIText();
DoLeftMenuAdvance(x24_tablegroup_leftmenu);
}
if (tbAction == CGameOptionsTouchBar::EAction::Back) {
x134_25_exitOptions = true;
CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
} else {
m_touchBar->SetSelection(-1, -1, -1);
}
}
}
}
return !x134_25_exitOptions;
@ -1841,9 +1643,6 @@ CFrontEndUI::CFrontEndUI() : CIOWin("FrontEndUI") {
for (int i = 0; CDvdFile::FileExists(GetAttractMovieFileName(i)); ++i)
++xc0_attractCount;
m_touchBar = NewFrontEndUITouchBar();
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
}
CFrontEndUI::~CFrontEndUI() {
@ -2008,23 +1807,9 @@ void CFrontEndUI::Draw() {
if (xec_emuFrme) {
xec_emuFrme->Draw(xdc_saveUI.get());
} else {
// g_Renderer->SetDepthReadWrite(false, false);
g_Renderer->SetViewportOrtho(false, -4096.f, 4096.f);
/* Correct movie aspect ratio */
float hPad, vPad;
if (CGraphics::GetViewportAspect() >= 1.78f) {
hPad = 1.78f / CGraphics::GetViewportAspect();
vPad = 1.78f / 1.33f;
} else {
hPad = 1.f;
vPad = CGraphics::GetViewportAspect() / 1.33f;
}
if ((xcc_curMoviePtr != nullptr) && xcc_curMoviePtr->GetIsFullyCached()) {
if ((xcc_curMoviePtr != nullptr)) {
/* Render movie */
xcc_curMoviePtr->SetFrame(hPad, vPad);
xcc_curMoviePtr->DrawFrame();
xcc_curMoviePtr->Draw();
}
if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) {
@ -2042,14 +1827,15 @@ void CFrontEndUI::Draw() {
if (x64_pressStartAlpha > 0.f && x38_pressStart.IsLoaded()) {
/* Render "Press Start" */
const zeus::CRectangle rect(0.5f - x38_pressStart->GetWidth() / 2.f / 640.f * hPad,
0.5f + (x38_pressStart->GetHeight() / 2.f - 240.f + 72.f) / 480.f * vPad,
x38_pressStart->GetWidth() / 640.f * hPad,
x38_pressStart->GetHeight() / 480.f * vPad);
zeus::CColor color = zeus::skWhite;
color.a() = x64_pressStartAlpha;
aurora::gfx::queue_textured_quad(aurora::gfx::CameraFilterType::Add, x38_pressStart->GetTexture(),
aurora::gfx::ZComp::Always, false, color, 1.f, rect, 0.f);
// TODO fixme
// const zeus::CRectangle rect(0.5f - x38_pressStart->GetWidth() / 2.f / 640.f * hPad,
// 0.5f + (x38_pressStart->GetHeight() / 2.f - 240.f + 72.f) / 480.f * vPad,
// x38_pressStart->GetWidth() / 640.f * hPad,
// x38_pressStart->GetHeight() / 480.f * vPad);
// zeus::CColor color = zeus::skWhite;
// color.a() = x64_pressStartAlpha;
// aurora::gfx::queue_textured_quad(aurora::gfx::CameraFilterType::Add, x38_pressStart->GetTexture(),
// aurora::gfx::ZComp::Always, false, color, 1.f, rect, 0.f);
}
if (xc0_attractCount > 0) {
@ -2189,14 +1975,10 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue&
if (x14_phase != EPhase::DisplayFrontEnd || input.ControllerIdx() != 0)
return;
/* Pop most recent action from Touch Bar */
CFrontEndUITouchBar::EAction touchBarAction = m_touchBar->PopAction();
if (x50_curScreen != x54_nextScreen) {
if (x54_nextScreen == EScreen::AttractMovie &&
(input.PStart() || input.PA() || input.PSpecialKey(aurora::SpecialKey::Esc) ||
input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary) ||
touchBarAction == CFrontEndUITouchBar::EAction::Start)) {
input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary))) {
/* Player wants to return to opening credits from attract movie */
SetFadeBlackTimer(std::min(1.f, x58_fadeBlackTimer));
PlayAdvanceSfx();
@ -2204,8 +1986,7 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue&
}
if (input.PA() || input.PStart() || input.PSpecialKey(aurora::SpecialKey::Esc) ||
input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary) ||
touchBarAction == CFrontEndUITouchBar::EAction::Start) {
input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) {
if (x50_curScreen == EScreen::OpenCredits && x54_nextScreen == EScreen::Title && x58_fadeBlackTimer > 1.f) {
/* Player is too impatient to view opening credits */
xd0_playerSkipToTitle = true;
@ -2216,13 +1997,11 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue&
} else {
if (x50_curScreen == EScreen::Title) {
if (input.PStart() || input.PA() || input.PSpecialKey(aurora::SpecialKey::Esc) ||
input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary) ||
touchBarAction == CFrontEndUITouchBar::EAction::Start) {
input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) {
if (x58_fadeBlackTimer < 30.f - g_tweakGame->GetPressStartDelay()) {
/* Proceed to file select UI */
CSfxManager::SfxStart(FETransitionBackSFX[x18_rndA][0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
CSfxManager::SfxStart(FETransitionBackSFX[x18_rndA][1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
StartStateTransition(EScreen::FileSelect);
return;
}
@ -2233,22 +2012,18 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue&
if (xf0_optionsFrme->ProcessUserInput(input, xdc_saveUI.get()))
return;
/* Exit options UI */
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
xf0_optionsFrme.reset();
return;
} else if (xe0_frontendCardFrme) {
/* Control FrontEnd with memory card */
switch (xe0_frontendCardFrme->ProcessUserInput(input, touchBarAction)) {
switch (xe0_frontendCardFrme->ProcessUserInput(input)) {
case SNewFileSelectFrame::EAction::FusionBonus:
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
StartStateTransition(EScreen::FusionBonus);
return;
case SNewFileSelectFrame::EAction::GameOptions:
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
xf0_optionsFrme = std::make_unique<SOptionsFrontEndFrame>();
return;
case SNewFileSelectFrame::EAction::SlideShow:
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
xd2_deferSlideShow = true;
StartSlideShow(queue);
return;
@ -2257,20 +2032,17 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue&
}
} else {
/* Control FrontEnd without memory card */
switch (xe8_frontendNoCardFrme->ProcessUserInput(input, touchBarAction)) {
switch (xe8_frontendNoCardFrme->ProcessUserInput(input)) {
case SFrontEndFrame::EAction::FusionBonus:
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
StartStateTransition(EScreen::FusionBonus);
return;
case SFrontEndFrame::EAction::GameOptions:
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
xf0_optionsFrme = std::make_unique<SOptionsFrontEndFrame>();
return;
case SFrontEndFrame::EAction::StartGame:
TransitionToGame();
return;
case SFrontEndFrame::EAction::SlideShow:
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
xd2_deferSlideShow = true;
StartSlideShow(queue);
return;
@ -2280,13 +2052,11 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue&
}
} else if (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus) {
/* Control Fusion bonus UI */
switch (xe4_fusionBonusFrme->ProcessUserInput(input, xdc_saveUI.get(), touchBarAction)) {
switch (xe4_fusionBonusFrme->ProcessUserInput(input, xdc_saveUI.get())) {
case SFusionBonusFrame::EAction::GoBack:
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
StartStateTransition(EScreen::FileSelect);
return;
case SFusionBonusFrame::EAction::PlayNESMetroid:
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
xf4_curAudio->StopMixing();
xec_emuFrme = std::make_unique<SNesEmulatorFrame>();
if (xdc_saveUI)
@ -2309,7 +2079,6 @@ void CFrontEndUI::TransitionToGame() {
CSfxManager::SfxStart(sfx[1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
x14_phase = EPhase::ToPlayGame;
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
StartStateTransition(EScreen::ToPlayGame);
}
@ -2355,11 +2124,11 @@ CIOWin::EMessageReturn CFrontEndUI::Update(float dt, CArchitectureQueue& queue)
case EPhase::LoadDeps:
/* Poll loading DGRP resources */
if (PumpLoad()) {
xe0_frontendCardFrme = std::make_unique<SNewFileSelectFrame>(xdc_saveUI.get(), x1c_rndB, *m_touchBar);
xe0_frontendCardFrme = std::make_unique<SNewFileSelectFrame>(xdc_saveUI.get(), x1c_rndB);
if (!g_Main->IsTrilogy()) {
xe4_fusionBonusFrme = std::make_unique<SFusionBonusFrame>(*m_touchBar);
xe4_fusionBonusFrme = std::make_unique<SFusionBonusFrame>();
}
xe8_frontendNoCardFrme = std::make_unique<SFrontEndFrame>(x1c_rndB, *m_touchBar);
xe8_frontendNoCardFrme = std::make_unique<SFrontEndFrame>(x1c_rndB);
x38_pressStart.GetObj();
CAudioSys::AddAudioGroup(x44_frontendAudioGrp->GetAudioGroupData());
xd4_audio1 = std::make_unique<CStaticAudioPlayer>("Audio/frontend_1.rsf", 416480, 1973664);
@ -2403,7 +2172,6 @@ CIOWin::EMessageReturn CFrontEndUI::Update(float dt, CArchitectureQueue& queue)
if (moviesReady) {
/* Ready to display FrontEnd */
x14_phase = EPhase::DisplayFrontEnd;
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::PressStart);
StartStateTransition(EScreen::Title);
} else {
return EMessageReturn::Exit;

View File

@ -5,7 +5,6 @@
#include <optional>
#include "Runtime/CGameDebug.hpp"
#include "Runtime/CGameOptionsTouchBar.hpp"
#include "Runtime/CIOWin.hpp"
#include "Runtime/CToken.hpp"
#include "Runtime/RetroTypes.hpp"
@ -16,7 +15,6 @@
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/GuiSys/CGuiTextSupport.hpp"
#include "Runtime/Input/CRumbleGenerator.hpp"
#include "Runtime/MP1/CFrontEndUITouchBar.hpp"
#include "Runtime/MP1/CGBASupport.hpp"
#include <zeus/CVector3f.hpp>
@ -110,14 +108,12 @@ public:
bool x10d_needsEraseToggle = false;
bool x10e_needsNewToggle = false;
CFrontEndUITouchBar& m_touchBar;
SNewFileSelectFrame(CSaveGameScreen* sui, u32 rnd, CFrontEndUITouchBar& touchBar);
SNewFileSelectFrame(CSaveGameScreen* sui, u32 rnd);
void FinishedLoading();
bool PumpLoad();
bool IsTextDoneAnimating() const;
void Update(float dt);
EAction ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction);
EAction ProcessUserInput(const CFinalInput& input);
void Draw() const;
void HandleActiveChange(CGuiTableGroup* active);
@ -177,7 +173,7 @@ public:
bool x40_linkInProgress;
void SetUIText(EUIType tp);
EAction ProcessUserInput(const CFinalInput& input, bool linkInProgress, CFrontEndUITouchBar::EAction tbAction);
EAction ProcessUserInput(const CFinalInput& input, bool linkInProgress);
void Update(float dt);
void FinishedLoading();
void Draw();
@ -199,16 +195,14 @@ public:
bool x39_fusionNotComplete = false;
bool x3a_mpNotComplete = false;
CFrontEndUITouchBar& m_touchBar;
bool m_gbaOverride = false;
explicit SFusionBonusFrame(CFrontEndUITouchBar& touchBar);
explicit SFusionBonusFrame();
void FinishedLoading();
bool PumpLoad();
void SetTableColors(CGuiTableGroup* tbgp) const;
void Update(float dt, CSaveGameScreen* saveUI);
EAction ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui, CFrontEndUITouchBar::EAction tbAction);
EAction ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui);
void Draw() const;
void ResetCompletionFlags() {
@ -232,13 +226,11 @@ public:
SGuiTextPair x1c_gbaPair;
SGuiTextPair x24_cheatPair;
CFrontEndUITouchBar& m_touchBar;
SFrontEndFrame(u32 rnd, CFrontEndUITouchBar& touchBar);
SFrontEndFrame(u32 rnd);
void FinishedLoading();
bool PumpLoad();
void Update(float dt);
EAction ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction);
EAction ProcessUserInput(const CFinalInput& input);
void Draw() const;
void HandleActiveChange(CGuiTableGroup* active);
@ -282,10 +274,6 @@ public:
bool x134_24_visible : 1 = true;
bool x134_25_exitOptions : 1 = false;
std::unique_ptr<CGameOptionsTouchBar> m_touchBar;
bool m_touchBarInValue = false;
bool m_touchBarValueDirty = false;
SOptionsFrontEndFrame();
void DoSliderChange(CGuiSliderGroup* caller, float value);
@ -349,10 +337,6 @@ private:
std::unique_ptr<SOptionsFrontEndFrame> xf0_optionsFrme;
CStaticAudioPlayer* xf4_curAudio = nullptr;
CColoredQuadFilter m_fadeToBlack{EFilterType::Blend};
std::unique_ptr<CFrontEndUITouchBar> m_touchBar;
void SetFadeBlackWithMovie() {
x58_fadeBlackTimer = 1000000.f;
x5c_fadeBlackWithMovie = true;
@ -370,7 +354,7 @@ private:
public:
CFrontEndUI();
~CFrontEndUI();
~CFrontEndUI() override;
void StartSlideShow(CArchitectureQueue& queue);
std::string GetAttractMovieFileName(int idx);
std::string GetNextAttractMovieFileName();

View File

@ -1,20 +0,0 @@
#include "Runtime/MP1/CFrontEndUITouchBar.hpp"
namespace metaforce {
CFrontEndUITouchBar::~CFrontEndUITouchBar() = default;
void CFrontEndUITouchBar::SetPhase(EPhase ph) { m_phase = ph; }
CFrontEndUITouchBar::EPhase CFrontEndUITouchBar::GetPhase() { return m_phase; }
void CFrontEndUITouchBar::SetFileSelectPhase(const SFileSelectDetail details[3], bool eraseGame, bool galleryActive) {
m_phase = EPhase::FileSelect;
}
void CFrontEndUITouchBar::SetNoCardSelectPhase(bool galleryActive) { m_phase = EPhase::NoCardSelect; }
void CFrontEndUITouchBar::SetFusionBonusPhase(bool fusionSuitActive) { m_phase = EPhase::FusionBonus; }
void CFrontEndUITouchBar::SetStartOptionsPhase(bool normalBeat) { m_phase = EPhase::StartOptions; }
CFrontEndUITouchBar::EAction CFrontEndUITouchBar::PopAction() { return EAction::None; }
//#ifndef __APPLE__
std::unique_ptr<CFrontEndUITouchBar> NewFrontEndUITouchBar() { return std::make_unique<CFrontEndUITouchBar>(); }
//#endif
} // namespace metaforce

View File

@ -1,49 +0,0 @@
#pragma once
#include <memory>
namespace metaforce {
class CFrontEndUITouchBar {
public:
enum class EPhase { None, PressStart, ProceedBack, StartOptions, EraseBack, FileSelect, NoCardSelect, FusionBonus };
enum class EAction {
None,
Start,
Normal,
Hard,
Back,
Confirm,
Options,
FileA,
FileB,
FileC,
Erase,
FusionBonus,
ImageGallery,
NESMetroid,
FusionSuit
};
enum class EFileState { New, Normal, Hard };
struct SFileSelectDetail {
EFileState state;
int percent;
};
protected:
EPhase m_phase = EPhase::None;
public:
virtual ~CFrontEndUITouchBar();
virtual void SetPhase(EPhase ph);
virtual EPhase GetPhase();
virtual void SetFileSelectPhase(const SFileSelectDetail details[3], bool eraseGame, bool galleryActive);
virtual void SetNoCardSelectPhase(bool galleryActive);
virtual void SetFusionBonusPhase(bool fusionSuitActive);
virtual void SetStartOptionsPhase(bool normalBeat);
virtual EAction PopAction();
};
std::unique_ptr<CFrontEndUITouchBar> NewFrontEndUITouchBar();
} // namespace metaforce

View File

@ -1,667 +0,0 @@
#include "CFrontEndUITouchBar.hpp"
#include "GameGlobalObjects.hpp"
#include "MP1/MP1.hpp"
#include <AppKit/AppKit.h>
#if !__has_feature(objc_arc)
#error ARC Required
#endif
extern "C" uint8_t START_BUTTON_2X[];
extern "C" size_t START_BUTTON_2X_SZ;
static NSColor *BlueConfirm() {
return [NSColor colorWithSRGBRed:0 / 255.f green:130 / 255.f blue:215 / 255.f alpha:1.f];
}
static NSColor *NormalModeColor() {
return [NSColor colorWithSRGBRed:0 / 255.f green:130 / 255.f blue:0 / 255.f alpha:1.f];
}
static NSColor *HardModeColor() { return [NSColor redColor]; }
static NSColor *FileColor(const metaforce::CFrontEndUITouchBar::SFileSelectDetail &detail) {
switch (detail.state) {
case metaforce::CFrontEndUITouchBar::EFileState::New:
return [NSColor darkGrayColor];
case metaforce::CFrontEndUITouchBar::EFileState::Normal:
return NormalModeColor();
case metaforce::CFrontEndUITouchBar::EFileState::Hard:
return HardModeColor();
}
}
@interface FrontEndUITouchBarPressStart : NSObject <NSTouchBarDelegate> {
@public
BOOL _startPressed;
}
- (IBAction)onPressStart:(id)sender;
@end
@implementation FrontEndUITouchBarPressStart
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"pressStartGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"pressStartGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"pressStartGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"pressStart" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"pressStart"]) {
NSData *imgData = [NSData dataWithBytesNoCopy:START_BUTTON_2X length:START_BUTTON_2X_SZ freeWhenDone:NO];
NSImage *img = [[NSImage alloc] initWithData:imgData];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Start" image:img target:self action:@selector(onPressStart:)];
button.imageHugsTitle = YES;
item.view = button;
return item;
}
return nil;
}
- (IBAction)onPressStart:(id)sender {
_startPressed = YES;
}
@end
@interface FrontEndUITouchBarProceedBack : NSObject <NSTouchBarDelegate> {
@public
metaforce::CFrontEndUITouchBar::EAction _action;
}
- (IBAction)onBack:(id)sender;
- (IBAction)onProceed:(id)sender;
@end
@implementation FrontEndUITouchBarProceedBack
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"proceedBackGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"proceedBackGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"proceedBackGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"back", @"proceed" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"back"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarGoBackTemplate]
target:self
action:@selector(onBack:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"proceed"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarGoForwardTemplate]
target:self
action:@selector(onProceed:)];
item.view = button;
return item;
}
return nil;
}
- (IBAction)onBack:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Back;
}
- (IBAction)onProceed:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Confirm;
}
@end
@interface FrontEndUITouchBarStartOptions : NSObject <NSTouchBarDelegate> {
@public
metaforce::CFrontEndUITouchBar::EAction _action;
BOOL _normalBeat;
}
- (IBAction)onStart:(id)sender;
- (IBAction)onNormal:(id)sender;
- (IBAction)onHard:(id)sender;
- (IBAction)onOptions:(id)sender;
- (IBAction)onCancel:(id)sender;
@end
@implementation FrontEndUITouchBarStartOptions
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"startOptionsGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"startOptionsGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"startOptionsGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = _normalBeat ? @[ @"cancel", @"normal", @"hard", @"options" ] : @[ @"cancel", @"start", @"options" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"start"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Start" target:self action:@selector(onStart:)];
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"normal"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Normal Mode" target:self action:@selector(onNormal:)];
button.bezelColor = NormalModeColor();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"hard"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Hard Mode" target:self action:@selector(onHard:)];
button.bezelColor = HardModeColor();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"options"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Options" target:self action:@selector(onOptions:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"cancel"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarGoBackTemplate]
target:self
action:@selector(onCancel:)];
item.view = button;
return item;
}
return nil;
}
- (IBAction)onStart:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Start;
}
- (IBAction)onNormal:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Normal;
}
- (IBAction)onHard:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Hard;
}
- (IBAction)onOptions:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Options;
}
- (IBAction)onCancel:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Back;
}
@end
@interface FrontEndUITouchBarEraseBack : NSObject <NSTouchBarDelegate> {
@public
metaforce::CFrontEndUITouchBar::EAction _action;
}
- (IBAction)onCancel:(id)sender;
- (IBAction)onErase:(id)sender;
@end
@implementation FrontEndUITouchBarEraseBack
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"eraseBackGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"eraseBackGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"eraseBackGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"cancel", @"erase" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"cancel"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Cancel" target:self action:@selector(onCancel:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"erase"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Erase" target:self action:@selector(onErase:)];
button.bezelColor = [NSColor redColor];
item.view = button;
return item;
}
return nil;
}
- (IBAction)onCancel:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Back;
}
- (IBAction)onErase:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Confirm;
}
@end
static NSString *GetFileSelectTitle(const metaforce::CFrontEndUITouchBar::SFileSelectDetail &detail, char letter) {
switch (detail.state) {
case metaforce::CFrontEndUITouchBar::EFileState::New:
return [NSString stringWithFormat:@"[New Game %c]", letter];
case metaforce::CFrontEndUITouchBar::EFileState::Normal:
return [NSString stringWithFormat:@"[Samus %c] %d%%", letter, detail.percent];
case metaforce::CFrontEndUITouchBar::EFileState::Hard:
return [NSString stringWithFormat:@"[Hard %c] %d%%", letter, detail.percent];
}
return @"";
}
@interface FrontEndUITouchBarFileSelect : NSObject <NSTouchBarDelegate> {
@public
metaforce::CFrontEndUITouchBar::SFileSelectDetail _details[3];
metaforce::CFrontEndUITouchBar::EAction _action;
BOOL _eraseGame;
BOOL _galleryActive;
}
- (IBAction)onFileA:(id)sender;
- (IBAction)onFileB:(id)sender;
- (IBAction)onFileC:(id)sender;
- (IBAction)onErase:(id)sender;
- (IBAction)onFusionBonus:(id)sender;
- (IBAction)onImageGallery:(id)sender;
@end
@implementation FrontEndUITouchBarFileSelect
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"fileSelectGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"fileSelectGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"fileSelectGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"fileA", @"fileB", @"fileC", @"erase", @"fusionBonus", @"imageGallery" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"fileA"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:GetFileSelectTitle(_details[0], 'A')
target:self
action:@selector(onFileA:)];
button.bezelColor = FileColor(_details[0]);
button.enabled = !_eraseGame || _details[0].state != metaforce::CFrontEndUITouchBar::EFileState::New;
item.view = button;
return item;
} else if ([identifier isEqualToString:@"fileB"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:GetFileSelectTitle(_details[1], 'B')
target:self
action:@selector(onFileB:)];
button.bezelColor = FileColor(_details[1]);
button.enabled = !_eraseGame || _details[1].state != metaforce::CFrontEndUITouchBar::EFileState::New;
item.view = button;
return item;
} else if ([identifier isEqualToString:@"fileC"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:GetFileSelectTitle(_details[2], 'C')
target:self
action:@selector(onFileC:)];
button.bezelColor = FileColor(_details[2]);
button.enabled = !_eraseGame || _details[2].state != metaforce::CFrontEndUITouchBar::EFileState::New;
item.view = button;
return item;
} else if ([identifier isEqualToString:@"erase"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
if (!_eraseGame) {
NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarDeleteTemplate]
target:self
action:@selector(onErase:)];
bool hasSave = false;
for (int i = 0; i < 3; ++i)
if (_details[i].state != metaforce::CFrontEndUITouchBar::EFileState::New) {
hasSave = true;
break;
}
button.enabled = hasSave;
item.view = button;
} else {
NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarGoBackTemplate]
target:self
action:@selector(onErase:)];
item.view = button;
}
return item;
} else if ([identifier isEqualToString:@"fusionBonus"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Bonuses" target:self action:@selector(onFusionBonus:)];
button.enabled = !_eraseGame;
item.view = button;
return item;
} else if ([identifier isEqualToString:@"imageGallery"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Gallery" target:self action:@selector(onImageGallery:)];
button.enabled = !_eraseGame && _galleryActive;
item.view = button;
return item;
}
return nil;
}
- (IBAction)onFileA:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::FileA;
}
- (IBAction)onFileB:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::FileB;
}
- (IBAction)onFileC:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::FileC;
}
- (IBAction)onErase:(id)sender {
if (!_eraseGame)
_action = metaforce::CFrontEndUITouchBar::EAction::Erase;
else
_action = metaforce::CFrontEndUITouchBar::EAction::Back;
}
- (IBAction)onFusionBonus:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::FusionBonus;
}
- (IBAction)onImageGallery:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::ImageGallery;
}
@end
@interface FrontEndUITouchBarNoCardSelect : NSObject <NSTouchBarDelegate> {
@public
metaforce::CFrontEndUITouchBar::EAction _action;
BOOL _galleryActive;
}
- (IBAction)onStart:(id)sender;
- (IBAction)onOptions:(id)sender;
- (IBAction)onFusionBonus:(id)sender;
- (IBAction)onImageGallery:(id)sender;
@end
@implementation FrontEndUITouchBarNoCardSelect
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"noCardSelectGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"noCardSelectGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"noCardSelectGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"start", @"fusionBonus", @"options", @"imageGallery" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"start"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Start" target:self action:@selector(onStart:)];
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"options"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Options" target:self action:@selector(onOptions:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"fusionBonus"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Fusion Bonuses" target:self action:@selector(onFusionBonus:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"imageGallery"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Image Gallery" target:self action:@selector(onImageGallery:)];
button.enabled = _galleryActive;
item.view = button;
return item;
}
return nil;
}
- (IBAction)onStart:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Start;
}
- (IBAction)onOptions:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Options;
}
- (IBAction)onFusionBonus:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::FusionBonus;
}
- (IBAction)onImageGallery:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::ImageGallery;
}
@end
@interface FrontEndUITouchBarFusionBonus : NSObject <NSTouchBarDelegate> {
@public
metaforce::CFrontEndUITouchBar::EAction _action;
BOOL _fusionSuitActive;
}
- (IBAction)onNESMetroid:(id)sender;
- (IBAction)onFusionSuit:(id)sender;
- (IBAction)onBack:(id)sender;
@end
@implementation FrontEndUITouchBarFusionBonus
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"fusionBonusGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"fusionBonusGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"fusionBonusGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"back", @"NESMetroid", @"fusionSuit" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"NESMetroid"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Play NES Metroid" target:self action:@selector(onNESMetroid:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"fusionSuit"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:@"Fusion Suit" target:self action:@selector(onFusionSuit:)];
if (_fusionSuitActive)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"back"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarGoBackTemplate]
target:self
action:@selector(onBack:)];
item.view = button;
return item;
}
return nil;
}
- (IBAction)onNESMetroid:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::NESMetroid;
}
- (IBAction)onFusionSuit:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::FusionSuit;
}
- (IBAction)onBack:(id)sender {
_action = metaforce::CFrontEndUITouchBar::EAction::Back;
}
@end
namespace metaforce {
class CFrontEndUITouchBarMac : public CFrontEndUITouchBar {
FrontEndUITouchBarPressStart *m_pressStartBar;
FrontEndUITouchBarProceedBack *m_proceedBackBar;
FrontEndUITouchBarStartOptions *m_startOptions;
FrontEndUITouchBarEraseBack *m_eraseBack;
FrontEndUITouchBarFileSelect *m_fileSelectBar;
FrontEndUITouchBarNoCardSelect *m_noCardSelectBar;
FrontEndUITouchBarFusionBonus *m_fusionBonusBar;
void Activate() {
id provider = nil;
switch (m_phase) {
case EPhase::PressStart:
provider = m_pressStartBar;
break;
case EPhase::ProceedBack:
provider = m_proceedBackBar;
break;
case EPhase::StartOptions:
provider = m_startOptions;
break;
case EPhase::EraseBack:
provider = m_eraseBack;
break;
case EPhase::FileSelect:
provider = m_fileSelectBar;
break;
case EPhase::NoCardSelect:
provider = m_noCardSelectBar;
break;
case EPhase::FusionBonus:
provider = m_fusionBonusBar;
break;
default:
break;
}
g_Main->GetMainWindow()->setTouchBarProvider((__bridge_retained void *)provider);
}
public:
CFrontEndUITouchBarMac() {
m_pressStartBar = [FrontEndUITouchBarPressStart new];
m_proceedBackBar = [FrontEndUITouchBarProceedBack new];
m_startOptions = [FrontEndUITouchBarStartOptions new];
m_eraseBack = [FrontEndUITouchBarEraseBack new];
m_fileSelectBar = [FrontEndUITouchBarFileSelect new];
m_noCardSelectBar = [FrontEndUITouchBarNoCardSelect new];
m_fusionBonusBar = [FrontEndUITouchBarFusionBonus new];
}
void SetPhase(EPhase ph) {
m_phase = ph;
Activate();
}
EPhase GetPhase() { return m_phase; }
void SetFileSelectPhase(const SFileSelectDetail details[3], bool eraseGame, bool galleryActive) {
m_fileSelectBar->_details[0] = details[0];
m_fileSelectBar->_details[1] = details[1];
m_fileSelectBar->_details[2] = details[2];
m_fileSelectBar->_eraseGame = eraseGame;
m_fileSelectBar->_galleryActive = galleryActive;
m_phase = EPhase::FileSelect;
Activate();
}
void SetNoCardSelectPhase(bool galleryActive) {
m_noCardSelectBar->_galleryActive = galleryActive;
m_phase = EPhase::NoCardSelect;
Activate();
}
void SetFusionBonusPhase(bool fusionSuitActive) {
m_fusionBonusBar->_fusionSuitActive = fusionSuitActive;
m_phase = EPhase::FusionBonus;
Activate();
}
void SetStartOptionsPhase(bool normalBeat) {
m_startOptions->_normalBeat = normalBeat;
m_phase = EPhase::StartOptions;
Activate();
}
EAction PopAction() {
switch (m_phase) {
case EPhase::PressStart:
if (m_pressStartBar->_startPressed) {
m_pressStartBar->_startPressed = NO;
return EAction::Start;
}
break;
case EPhase::ProceedBack:
if (m_proceedBackBar->_action != EAction::None) {
EAction action = m_proceedBackBar->_action;
m_proceedBackBar->_action = EAction::None;
return action;
}
break;
case EPhase::StartOptions:
if (m_startOptions->_action != EAction::None) {
EAction action = m_startOptions->_action;
m_startOptions->_action = EAction::None;
return action;
}
break;
case EPhase::EraseBack:
if (m_eraseBack->_action != EAction::None) {
EAction action = m_eraseBack->_action;
m_eraseBack->_action = EAction::None;
return action;
}
break;
case EPhase::FileSelect:
if (m_fileSelectBar->_action != EAction::None) {
EAction action = m_fileSelectBar->_action;
m_fileSelectBar->_action = EAction::None;
return action;
}
break;
case EPhase::NoCardSelect:
if (m_noCardSelectBar->_action != EAction::None) {
EAction action = m_noCardSelectBar->_action;
m_noCardSelectBar->_action = EAction::None;
return action;
}
break;
case EPhase::FusionBonus:
if (m_fusionBonusBar->_action != EAction::None) {
EAction action = m_fusionBonusBar->_action;
m_fusionBonusBar->_action = EAction::None;
return action;
}
break;
default:
break;
}
return EAction::None;
}
};
std::unique_ptr<CFrontEndUITouchBar> NewFrontEndUITouchBar() { return std::make_unique<CFrontEndUITouchBarMac>(); }
}

View File

@ -1,11 +1,5 @@
add_subdirectory(World)
#if (APPLE)
# set(MP1_PLAT_SOURCES
# CFrontEndUITouchBarMac.mm
# CSaveGameScreenTouchBarMac.mm)
#endif ()
set(MP1_SOURCES
Tweaks/CTweakAutoMapper.hpp Tweaks/CTweakAutoMapper.cpp
Tweaks/CTweakBall.hpp Tweaks/CTweakBall.cpp
@ -27,11 +21,9 @@ set(MP1_SOURCES
CMFGame.hpp CMFGame.cpp
CPlayMovie.hpp CPlayMovie.cpp
CFrontEndUI.hpp CFrontEndUI.cpp
CFrontEndUITouchBar.hpp CFrontEndUITouchBar.cpp
CPreFrontEnd.hpp CPreFrontEnd.cpp
CSlideShow.hpp CSlideShow.cpp
CSaveGameScreen.hpp CSaveGameScreen.cpp
CSaveGameScreenTouchBar.hpp CSaveGameScreenTouchBar.cpp
CMemoryCardDriver.hpp CMemoryCardDriver.cpp
CQuitGameScreen.hpp CQuitGameScreen.cpp
CMessageScreen.hpp CMessageScreen.cpp

View File

@ -350,8 +350,6 @@ void CSaveGameScreen::SetUIText() {
x68_textpane_choice3->TextSupport().SetText(opt3Str);
m_touchBar->SetUIOpts(opt0Str, opt1Str, opt2Str);
x5c_textpane_choice0->SetIsSelectable(opt0 != -1);
x60_textpane_choice1->SetIsSelectable(opt1 != -1);
x64_textpane_choice2->SetIsSelectable(opt2 != -1);
@ -597,13 +595,6 @@ void CSaveGameScreen::DoSelectionChange([[maybe_unused]] CGuiTableGroup* caller,
void CSaveGameScreen::ProcessUserInput(const CFinalInput& input) {
if (x50_loadedFrame != nullptr) {
x50_loadedFrame->ProcessUserInput(input);
int tbOpt = m_touchBar->PopOption();
if (tbOpt != -1) {
x58_tablegroup_choices->SetUserSelection(tbOpt);
SetUIColors();
DoAdvance(x58_tablegroup_choices);
}
}
}
@ -637,7 +628,7 @@ const CGameState::GameFileStateInfo* CSaveGameScreen::GetGameData(int idx) const
}
CSaveGameScreen::CSaveGameScreen(ESaveContext saveCtx, u64 serial)
: x0_saveCtx(saveCtx), x8_serial(serial), m_touchBar(NewSaveUITouchBar()) {
: x0_saveCtx(saveCtx), x8_serial(serial) {
x14_txtrSaveBanner = g_SimplePool->GetObj("TXTR_SaveBanner");
x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0");
x2c_txtrSaveIcon1 = g_SimplePool->GetObj("TXTR_SaveIcon1");

View File

@ -7,7 +7,6 @@
#include "Runtime/CToken.hpp"
#include "Runtime/GuiSys/CGuiFrame.hpp"
#include "Runtime/MP1/CMemoryCardDriver.hpp"
#include "Runtime/MP1/CSaveGameScreenTouchBar.hpp"
#include "Runtime/RetroTypes.hpp"
namespace metaforce {
@ -85,8 +84,6 @@ private:
bool x92_savingDisabled = false;
bool x93_inGame;
std::unique_ptr<CSaveGameScreenTouchBar> m_touchBar;
void ContinueWithoutSaving();
public:

View File

@ -1,12 +0,0 @@
#include "Runtime/MP1/CSaveGameScreenTouchBar.hpp"
namespace metaforce::MP1 {
int CSaveGameScreenTouchBar::PopOption() { return -1; }
void CSaveGameScreenTouchBar::SetUIOpts(std::u16string_view opt0, std::u16string_view opt1, std::u16string_view opt2) {}
//#ifndef __APPLE__
std::unique_ptr<CSaveGameScreenTouchBar> NewSaveUITouchBar() { return std::make_unique<CSaveGameScreenTouchBar>(); }
//#endif
} // namespace metaforce::MP1

View File

@ -1,18 +0,0 @@
#pragma once
#include <memory>
#include <string>
#include <utility>
namespace metaforce::MP1 {
class CSaveGameScreenTouchBar {
public:
virtual ~CSaveGameScreenTouchBar() = default;
virtual int PopOption();
virtual void SetUIOpts(std::u16string_view opt0, std::u16string_view opt1, std::u16string_view opt2);
};
std::unique_ptr<CSaveGameScreenTouchBar> NewSaveUITouchBar();
} // namespace metaforce::MP1

View File

@ -1,101 +0,0 @@
#include "CSaveGameScreenTouchBar.hpp"
#include "GameGlobalObjects.hpp"
#include "MP1/MP1.hpp"
#include <AppKit/AppKit.h>
#if !__has_feature(objc_arc)
#error ARC Required
#endif
@interface SaveGameScreenTouchBar : NSObject <NSTouchBarDelegate> {
@public
NSString *_opts[3];
int _opt;
}
- (IBAction)onOpt0:(id)sender;
- (IBAction)onOpt1:(id)sender;
- (IBAction)onOpt2:(id)sender;
@end
@implementation SaveGameScreenTouchBar
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"saveUIGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"saveUIGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"saveUIGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items;
items = [NSMutableArray arrayWithCapacity:3];
[items addObject:@"back"];
for (int i = 0; i < 3 && _opts[i]; ++i)
[items addObject:[NSString stringWithFormat:@"opt%d", i]];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"opt0"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:_opts[0] target:self action:@selector(onOpt0:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"opt1"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:_opts[1] target:self action:@selector(onOpt1:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"opt2"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:_opts[2] target:self action:@selector(onOpt2:)];
item.view = button;
return item;
}
return nil;
}
- (IBAction)onOpt0:(id)sender {
_opt = 0;
}
- (IBAction)onOpt1:(id)sender {
_opt = 1;
}
- (IBAction)onOpt2:(id)sender {
_opt = 2;
}
@end
namespace metaforce::MP1 {
class CSaveGameScreenTouchBarMac : public CSaveGameScreenTouchBar {
SaveGameScreenTouchBar *m_touchBar;
public:
CSaveGameScreenTouchBarMac() {
m_touchBar = [SaveGameScreenTouchBar new];
m_touchBar->_opt = -1;
}
int PopOption() {
if (m_touchBar->_opt != -1) {
int opt = m_touchBar->_opt;
m_touchBar->_opt = -1;
return opt;
}
return -1;
}
void SetUIOpts(std::u16string_view opt0, std::u16string_view opt1, std::u16string_view opt2) {
m_touchBar->_opts[0] = opt0.size() ? [NSString stringWithUTF8String:hecl::Char16ToUTF8(opt0).c_str()] : nil;
m_touchBar->_opts[1] = opt1.size() ? [NSString stringWithUTF8String:hecl::Char16ToUTF8(opt1).c_str()] : nil;
m_touchBar->_opts[2] = opt2.size() ? [NSString stringWithUTF8String:hecl::Char16ToUTF8(opt2).c_str()] : nil;
g_Main->GetMainWindow()->setTouchBarProvider((__bridge_retained void *)m_touchBar);
}
};
std::unique_ptr<CSaveGameScreenTouchBar> NewSaveUITouchBar() { return std::make_unique<CSaveGameScreenTouchBarMac>(); }
}

View File

@ -257,7 +257,7 @@ void CGameGlobalObjects::AddPaksAndFactories() {
}
if (CFactoryMgr* fmgr = g_ResFactory->GetFactoryMgr()) {
fmgr->AddFactory(FOURCC('TXTR'), FMemFactoryFunc(FTextureFactory));
fmgr->AddFactory(FOURCC('TXTR'), FFactoryFunc(FTextureFactory));
fmgr->AddFactory(FOURCC('PART'), FFactoryFunc(FParticleFactory));
fmgr->AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame));
fmgr->AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory));

View File

@ -1410,7 +1410,7 @@ void CThardus::RenderFlare(const CStateManager& mgr, float t) {
CGraphics::SetModelMatrix(zeus::CTransform());
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
CGraphics::SetTevOp(0, CGraphics::sTevPass805a5ebc);
CGraphics::SetTevOp(1, CGraphics::sTevPass805a564c);
CGraphics::SetTevOp(1, CGraphics::skPassThru);
CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false);
CGraphics::StreamColor(zeus::CColor(f1, f1));
CGraphics::StreamBegin(0xa0);

View File

@ -209,12 +209,13 @@ CElementGen::CElementGen(TToken<CGenDescription> gen, EModelOrientationType orie
if (x26c_31_LINE) {
CUVElement* texr = desc->x54_x40_TEXR.get();
aurora::gfx::TextureHandle tex;
if (texr)
tex = texr->GetValueTexture(0).GetObj()->GetTexture();
// TODO
// aurora::gfx::TextureHandle tex;
// if (texr)
// tex = texr->GetValueTexture(0).GetObj()->GetTexture();
int maxVerts = x90_MAXP;
m_lineRenderer.reset(
new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, tex, x26c_26_AAPH, x26c_28_zTest));
// m_lineRenderer.reset(
// new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, tex, x26c_26_AAPH, x26c_28_zTest));
} else {
m_shaderClass = CElementGenShaders::GetShaderClass(*this);
}
@ -918,7 +919,7 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
CParticle& target = x30_particles[0];
int partFrame = x74_curFrame - target.x28_startFrame;
cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::Repeat);
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
/* Shade as TEXC * RASC and TEXA * RASA */
if (moveRedToAlphaBuffer) {
/* Color = Prev.rgb * Prev.a */
@ -1043,7 +1044,7 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
if (!texConst) {
CTexture* tex = texr->GetValueTexture(x74_curFrame - particle.x28_startFrame).GetObj();
if (tex != cachedTex) {
tex->Load(0, CTexture::EClampMode::Repeat);
tex->Load(GX::TEXMAP0, EClampMode::Repeat);
cachedTex = tex;
}
}
@ -1157,7 +1158,7 @@ void CElementGen::RenderLines() {
CParticle& target = x30_particles[0];
int partFrame = x74_curFrame - target.x28_startFrame;
cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::Repeat);
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
/* Set TEXC * RASC */
@ -1187,7 +1188,7 @@ void CElementGen::RenderLines() {
if (!constTexr) {
CTexture* tex = texr->GetValueTexture(partFrame).GetObj();
if (tex != cachedTex) {
tex->Load(0, CTexture::EClampMode::Repeat);
tex->Load(GX::TEXMAP0, EClampMode::Repeat);
cachedTex = tex;
}
}
@ -1264,7 +1265,7 @@ void CElementGen::RenderParticles() {
CParticle& target = x30_particles[0];
int partFrame = x74_curFrame - target.x28_startFrame;
cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::Repeat);
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
if (x338_moduColor != zeus::skBlack) {
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
@ -1678,7 +1679,7 @@ void CElementGen::RenderParticlesIndirectTexture() {
CParticle& firstParticle = x30_particles[0];
int partFrame = x74_curFrame - firstParticle.x28_startFrame;
CTexture* cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::Repeat);
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
bool constTexr = texr->HasConstantTexture();
@ -1687,7 +1688,7 @@ void CElementGen::RenderParticlesIndirectTexture() {
CUVElement* tind = desc->x58_x44_TIND.get();
CTexture* cachedIndTex = tind->GetValueTexture(partFrame).GetObj();
cachedIndTex->Load(2, CTexture::EClampMode::Repeat);
cachedIndTex->Load(GX::TEXMAP2, EClampMode::Repeat);
SUVElementSet uvsInd = {0.f, 0.f, 1.f, 1.f};
bool constIndTexr = tind->HasConstantTexture();
@ -1734,7 +1735,7 @@ void CElementGen::RenderParticlesIndirectTexture() {
if (!constTexr) {
CTexture* tex = texr->GetValueTexture(thisPartFrame).GetObj();
if (tex != cachedTex) {
tex->Load(0, CTexture::EClampMode::Repeat);
tex->Load(GX::TEXMAP0, EClampMode::Repeat);
cachedTex = tex;
}
}
@ -1742,7 +1743,7 @@ void CElementGen::RenderParticlesIndirectTexture() {
if (!constIndTexr) {
CTexture* tex = tind->GetValueTexture(thisPartFrame).GetObj();
if (tex != cachedIndTex) {
tex->Load(2, CTexture::EClampMode::Repeat);
tex->Load(GX::TEXMAP2, EClampMode::Repeat);
cachedIndTex = tex;
}
}

View File

@ -60,7 +60,7 @@ CPlasmaProjectile::CPlasmaProjectile(const TToken<CWeaponDescription>& wDesc, st
x51c_pulseGen->SetParticleEmission(false);
// CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) {
m_renderObjs.emplace(x4e8_texture->GetTexture(), x4f4_glowTexture->GetTexture());
// m_renderObjs.emplace(x4e8_texture->GetTexture(), x4f4_glowTexture->GetTexture());
// return true;
// } BooTrace);
}

View File

@ -28,8 +28,9 @@ CEnvFxManagerGrid::CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus
, x1c_particles(std::move(initialParticles))
//, m_instBuf(parent.m_instPool.allocateBlock(CGraphics::g_BooFactory, reserve))
//, m_uniformBuf(parent.m_uniformPool.allocateBlock(CGraphics::g_BooFactory))
, m_lineRenderer(CLineRenderer::EPrimitiveMode::Lines, reserve * 2, parent.x40_txtrEnvGradient->GetTexture(),
true, true) {
//, m_lineRenderer(CLineRenderer::EPrimitiveMode::Lines, reserve * 2, parent.x40_txtrEnvGradient->GetTexture(),
// true, true)
{
x1c_particles.reserve(reserve);
CEnvFxShaders::BuildShaderDataBinding(parent, *this);
}
@ -394,7 +395,7 @@ void CEnvFxManagerGrid::RenderSnowParticles(const zeus::CTransform& camXf) {
}
void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) {
m_lineRenderer.Reset();
// m_lineRenderer.Reset();
const float zOffset = 2.f * (1.f - std::fabs(camXf.basis[2].dot(zeus::skUp))) + 1.f;
const zeus::CColor color0(1.f, 10.f / 15.f);
for (const auto& particle : x1c_particles) {
@ -403,10 +404,10 @@ void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) {
pos1.z() += zOffset;
const float uvy0 = pos0.z() * 10.f + m_uvyOffset;
const float uvy1 = pos1.z() * 10.f + m_uvyOffset;
m_lineRenderer.AddVertex(pos0, zeus::skWhite, 1.f, {0.f, uvy0});
m_lineRenderer.AddVertex(pos1, zeus::skClear, 1.f, {0.f, uvy1});
// m_lineRenderer.AddVertex(pos0, zeus::skWhite, 1.f, {0.f, uvy0});
// m_lineRenderer.AddVertex(pos1, zeus::skClear, 1.f, {0.f, uvy1});
}
m_lineRenderer.Render(false, zeus::CColor(1.f, 0.15f)); // g_Renderer->IsThermalVisorHotPass()
// m_lineRenderer.Render(false, zeus::CColor(1.f, 0.15f)); // g_Renderer->IsThermalVisorHotPass()
}
void CEnvFxManagerGrid::RenderUnderwaterParticles(const zeus::CTransform& camXf) {

View File

@ -60,7 +60,7 @@ class CEnvFxManagerGrid {
// hecl::VertexBufferPool<CEnvFxShaders::Instance>::Token m_instBuf;
// hecl::UniformBufferPool<CEnvFxShaders::Uniform>::Token m_uniformBuf;
CLineRenderer m_lineRenderer;
// CLineRenderer m_lineRenderer;
//
// boo::ObjToken<boo::IShaderDataBinding> m_snowBinding;
// boo::ObjToken<boo::IShaderDataBinding> m_underwaterBinding;

View File

@ -135,7 +135,7 @@ void CFluidPlaneManager::SetupRippleMap() {
curX += (1.f / 63.f);
}
RippleMapTex = aurora::gfx::new_static_texture_2d(64, 64, 1, aurora::gfx::TextureFormat::R8,
RippleMapTex = aurora::gfx::new_static_texture_2d(64, 64, 1, ETexelFormat::R8PC,
{reinterpret_cast<const uint8_t*>(RippleValues.data()), 64 * 64},
"Ripple Map");
}

View File

@ -3,7 +3,7 @@
namespace metaforce {
CProjectedShadow::CProjectedShadow(u32 w, u32 h, bool persistent)
: x0_texture(CTexture(ETexelFormat::I4, w, h, 1)), x81_persistent(persistent) {}
: x0_texture(CTexture(ETexelFormat::I4, w, h, 1, "Projected Shadow Texture")), x81_persistent(persistent) {}
zeus::CAABox CProjectedShadow::CalculateRenderBounds() { return {}; }

View File

@ -27,9 +27,11 @@ add_library(aurora STATIC
lib/gfx/movie_player/shader.cpp
lib/gfx/textured_quad/shader.cpp
lib/gfx/colored_quad/shader.cpp
lib/gfx/stream.cpp
lib/gfx/texture_convert.cpp
)
target_compile_definitions(aurora PRIVATE IMGUI_USER_CONFIG="imconfig_user.h") # IMGUI_USE_WCHAR32
target_include_directories(aurora PUBLIC include ../ )
target_include_directories(aurora PUBLIC include ../)
target_include_directories(aurora PRIVATE ../imgui ../extern/imgui)
target_include_directories(aurora PRIVATE
../extern/dawn/src

View File

@ -396,3 +396,68 @@ constexpr wzstring_view operator""_zsv(const wchar_t* str, std::size_t len) noex
} // namespace zstring_view_literals
} // namespace literals
} // namespace aurora
template <typename BitType>
class Flags {
public:
using MaskType = typename std::underlying_type<BitType>::type;
// constructors
constexpr Flags() noexcept : m_mask(0) {}
constexpr Flags(BitType bit) noexcept : m_mask(static_cast<MaskType>(bit)) {}
constexpr Flags(Flags<BitType> const& rhs) noexcept : m_mask(rhs.m_mask) {}
constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {}
[[nodiscard]] constexpr bool IsSet(Flags<BitType> const bit) const noexcept { return bool(*this & bit); }
// relational operators
auto operator<=>(Flags<BitType> const&) const noexcept = default;
// logical operator
constexpr bool operator!() const noexcept { return !m_mask; }
// bitwise operators
constexpr Flags<BitType> operator&(Flags<BitType> const& rhs) const noexcept {
return Flags<BitType>(m_mask & rhs.m_mask);
}
constexpr Flags<BitType> operator|(Flags<BitType> const& rhs) const noexcept {
return Flags<BitType>(m_mask | rhs.m_mask);
}
constexpr Flags<BitType> operator^(Flags<BitType> const& rhs) const noexcept {
return Flags<BitType>(m_mask ^ rhs.m_mask);
}
// assignment operators
constexpr Flags<BitType>& operator=(Flags<BitType> const& rhs) noexcept {
m_mask = rhs.m_mask;
return *this;
}
constexpr Flags<BitType>& operator|=(Flags<BitType> const& rhs) noexcept {
m_mask |= rhs.m_mask;
return *this;
}
constexpr Flags<BitType>& operator&=(Flags<BitType> const& rhs) noexcept {
m_mask &= rhs.m_mask;
return *this;
}
constexpr Flags<BitType>& operator^=(Flags<BitType> const& rhs) noexcept {
m_mask ^= rhs.m_mask;
return *this;
}
// cast operators
explicit constexpr operator bool() const noexcept { return m_mask != 0; }
explicit constexpr operator MaskType() const noexcept { return m_mask; }
private:
MaskType m_mask;
};

View File

@ -2,6 +2,9 @@
#include "common.hpp"
// TODO make this shared?
#include "../../../Runtime/Graphics/GX.hpp"
#include <cstdint>
#include <utility>
@ -79,6 +82,50 @@ enum class ERglAlphaOp { And = 0, Or = 1, Xor = 2, XNor = 3 };
enum class ERglEnum { Never = 0, Less = 1, Equal = 2, LEqual = 3, Greater = 4, NEqual = 5, GEqual = 6, Always = 7 };
enum class ERglTevStage : u32 {
Stage0,
Stage1,
Stage2,
Stage3,
Stage4,
Stage5,
Stage6,
Stage7,
Stage8,
Stage9,
Stage10,
Stage11,
Stage12,
Stage13,
Stage14,
Stage15,
MAX
};
enum class ETexelFormat {
Invalid = -1,
I4 = 0,
I8 = 1,
IA4 = 2,
IA8 = 3,
C4 = 4,
C8 = 5,
C14X2 = 6,
RGB565 = 7,
RGB5A3 = 8,
RGBA8 = 9,
CMPR = 10,
// Metaforce addition: non-converting formats
RGBA8PC = 11,
R8PC = 12,
};
enum class EClampMode {
Clamp,
Repeat,
Mirror,
};
struct CFogState {
zeus::CColor m_color;
float m_A = 0.f;
@ -86,6 +133,41 @@ struct CFogState {
float m_C = 0.f;
ERglFogMode m_mode;
};
enum class EStreamFlagBits : u8 {
fHasNormal = 0x1,
fHasColor = 0x2,
fHasTexture = 0x3,
};
using EStreamFlags = Flags<EStreamFlagBits>;
namespace CTevCombiners {
struct CTevOp {
bool x0_clamp = true;
GX::TevOp x4_op = GX::TevOp::TEV_ADD;
GX::TevBias x8_bias = GX::TevBias::TB_ZERO;
GX::TevScale xc_scale = GX::TevScale::CS_SCALE_1;
GX::TevRegID xc_regId = GX::TevRegID::TEVPREV;
bool operator<=>(const CTevOp&) const = default;
};
struct ColorPass {
GX::TevColorArg x0_a;
GX::TevColorArg x4_b;
GX::TevColorArg x8_c;
GX::TevColorArg xc_d;
bool operator<=>(const ColorPass&) const = default;
};
struct AlphaPass {
GX::TevAlphaArg x0_a;
GX::TevAlphaArg x4_b;
GX::TevAlphaArg x8_c;
GX::TevAlphaArg xc_d;
bool operator<=>(const AlphaPass&) const = default;
};
} // namespace CTevCombiners
} // namespace metaforce
namespace aurora::gfx {
@ -138,6 +220,16 @@ enum class ZComp : uint8_t {
[[nodiscard]] bool get_dxt_compression_supported() noexcept;
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp) noexcept;
void update_tev_stage(metaforce::ERglTevStage stage, const metaforce::CTevCombiners::ColorPass& colPass,
const metaforce::CTevCombiners::AlphaPass& alphaPass,
const metaforce::CTevCombiners::CTevOp& colorOp,
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept;
void stream_begin(GX::Primitive primitive) noexcept;
void stream_vertex(metaforce::EStreamFlags flags, const zeus::CVector3f& pos, const zeus::CVector3f& nrm,
const zeus::CColor& color, const zeus::CVector2f& uv) noexcept;
void stream_end() noexcept;
// GX state
void set_cull_mode(metaforce::ERglCullMode mode) noexcept;
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst,
@ -177,11 +269,12 @@ void queue_colored_quad_verts(CameraFilterType filter_type, ZComp z_comparison,
void queue_colored_quad(CameraFilterType filter_type, ZComp z_comparison, bool z_test, const zeus::CColor& color,
const zeus::CRectangle& rect, float z) noexcept;
void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v,
const zeus::CColor& color, float h_pad, float v_pad) noexcept;
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
const zeus::CVector3f& v4) noexcept;
TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mips, TextureFormat format,
TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mips, metaforce::ETexelFormat format,
ArrayRef<uint8_t> data, zstring_view label) noexcept;
TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, TextureFormat format,
TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, metaforce::ETexelFormat format,
zstring_view label) noexcept;
TextureHandle new_render_texture(uint32_t width, uint32_t height, uint32_t color_bind_count, uint32_t depth_bind_count,
zstring_view label) noexcept;

View File

@ -203,8 +203,9 @@ PipelineRef pipeline_ref(colored_quad::PipelineConfig config) {
}
void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v,
const zeus::CColor& color, float h_pad, float v_pad) noexcept {
auto data = movie_player::make_draw_data(g_state.moviePlayer, tex_y, tex_u, tex_v, color, h_pad, v_pad);
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
const zeus::CVector3f& v4) noexcept {
auto data = movie_player::make_draw_data(g_state.moviePlayer, tex_y, tex_u, tex_v, v1, v2, v3, v4);
push_draw_command({.type = ShaderType::MoviePlayer, .moviePlayer = data});
}
template <>

View File

@ -21,18 +21,38 @@ static inline XXH64_hash_t xxh3_hash(const T& input, XXH64_hash_t seed = 0) {
class ByteBuffer {
public:
ByteBuffer() = default;
explicit ByteBuffer(size_t capacity) : m_data(static_cast<uint8_t*>(calloc(1, capacity))), m_capacity(capacity) {}
~ByteBuffer() {
ByteBuffer() noexcept = default;
explicit ByteBuffer(size_t size) noexcept
: m_data(static_cast<uint8_t*>(calloc(1, size))), m_length(size), m_capacity(size) {}
~ByteBuffer() noexcept {
if (m_data != nullptr) {
free(m_data);
}
}
ByteBuffer(ByteBuffer&& rhs) noexcept : m_data(rhs.m_data), m_length(rhs.m_length), m_capacity(rhs.m_capacity) {
rhs.m_data = nullptr;
rhs.m_length = 0;
rhs.m_capacity = 0;
}
ByteBuffer& operator=(ByteBuffer&& rhs) noexcept {
if (m_data != nullptr) {
free(m_data);
}
m_data = rhs.m_data;
m_length = rhs.m_length;
m_capacity = rhs.m_capacity;
rhs.m_data = nullptr;
rhs.m_length = 0;
rhs.m_capacity = 0;
return *this;
}
ByteBuffer(ByteBuffer const&) = delete;
ByteBuffer& operator=(ByteBuffer const&) = delete;
uint8_t* data() { return m_data; }
const uint8_t* data() const { return m_data; }
size_t size() const { return m_length; }
[[nodiscard]] uint8_t* data() noexcept { return m_data; }
[[nodiscard]] const uint8_t* data() const noexcept { return m_data; }
[[nodiscard]] size_t size() const noexcept { return m_length; }
[[nodiscard]] bool empty() const noexcept { return m_length == 0; }
void append(const void* data, size_t size) {
resize(m_length + size);
@ -136,9 +156,17 @@ struct TextureRef {
wgpu::TextureView view;
wgpu::Extent3D size;
wgpu::TextureFormat format;
uint32_t mipCount;
metaforce::ETexelFormat gameFormat;
TextureRef(wgpu::Texture&& texture, wgpu::TextureView&& view, wgpu::Extent3D size, wgpu::TextureFormat format)
: texture(std::move(texture)), view(std::move(view)), size(size), format(format) {}
TextureRef(wgpu::Texture&& texture, wgpu::TextureView&& view, wgpu::Extent3D size, wgpu::TextureFormat format,
uint32_t mipCount, metaforce::ETexelFormat gameFormat = metaforce::ETexelFormat::Invalid)
: texture(std::move(texture))
, view(std::move(view))
, size(size)
, format(format)
, mipCount(mipCount)
, gameFormat(gameFormat) {}
};
using PipelineRef = uint64_t;

View File

@ -219,20 +219,21 @@ wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] Pipeli
}
DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const TextureHandle& tex_u,
const TextureHandle& tex_v, const zeus::CColor& color, float h_pad, float v_pad) {
const TextureHandle& tex_v, const zeus::CVector3f& v1, const zeus::CVector3f& v2,
const zeus::CVector3f& v3, const zeus::CVector3f& v4) {
auto pipeline = pipeline_ref(PipelineConfig{});
const std::array verts{
Vert{{-h_pad, v_pad, 0.f}, {0.0, 0.0}},
Vert{{-h_pad, -v_pad, 0.f}, {0.0, 1.0}},
Vert{{h_pad, v_pad, 0.f}, {1.0, 0.0}},
Vert{{h_pad, -v_pad, 0.f}, {1.0, 1.0}},
Vert{{v1.x(), v1.z(), v1.y()}, {0.0, 0.0}},
Vert{{v2.x(), v2.z(), v2.y()}, {0.0, 1.0}},
Vert{{v3.x(), v3.z(), v3.y()}, {1.0, 0.0}},
Vert{{v4.x(), v4.z(), v4.y()}, {1.0, 1.0}},
};
const auto vertRange = push_verts(ArrayRef{verts});
const auto uniform = Uniform{
.xf = Mat4x4_Identity,
.color = color,
.color = zeus::skWhite,
};
const auto uniformRange = push_uniform(uniform);

View File

@ -36,6 +36,7 @@ struct alignas(4) Uniform {
State construct_state();
wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] PipelineConfig config);
DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const TextureHandle& tex_u,
const TextureHandle& tex_v, const zeus::CColor& color, float h_pad, float v_pad);
const TextureHandle& tex_v, const zeus::CVector3f& v1, const zeus::CVector3f& v2,
const zeus::CVector3f& v3, const zeus::CVector3f& v4);
void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass);
} // namespace aurora::gfx::movie_player

15
aurora/lib/gfx/stream.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "common.hpp"
namespace aurora::gfx {
constexpr u32 maxTevStages = 2;
//static std::array<STevStage, maxTevStages> sTevStages;
void update_tev_stage(metaforce::ERglTevStage stage, const metaforce::CTevCombiners::ColorPass& colPass,
const metaforce::CTevCombiners::AlphaPass& alphaPass,
const metaforce::CTevCombiners::CTevOp& colorOp,
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept {}
void stream_begin(GX::Primitive primitive) noexcept {}
void stream_vertex(metaforce::EStreamFlags flags, const zeus::CVector3f& pos, const zeus::CVector3f& nrm,
const zeus::CColor& color, const zeus::CVector2f& uv) noexcept {}
void stream_end() noexcept {}
} // namespace aurora::gfx

View File

@ -1,6 +1,7 @@
#include "common.hpp"
#include "../gpu.hpp"
#include "texture_convert.hpp"
#include <logvisor/logvisor.hpp>
#include <magic_enum.hpp>
@ -11,24 +12,6 @@ static logvisor::Module Log("aurora::gfx");
using gpu::g_device;
using gpu::g_queue;
static wgpu::TextureFormat to_wgpu(TextureFormat format) {
switch (format) {
case TextureFormat::RGBA8:
return wgpu::TextureFormat::RGBA8Unorm;
case TextureFormat::R8:
return wgpu::TextureFormat::R8Unorm;
case TextureFormat::R32Float:
return wgpu::TextureFormat::R32Float;
case TextureFormat::DXT1:
return wgpu::TextureFormat::BC1RGBAUnorm;
case TextureFormat::DXT3:
return wgpu::TextureFormat::BC3RGBAUnorm;
case TextureFormat::DXT5:
return wgpu::TextureFormat::BC5RGUnorm;
case TextureFormat::BPTC:
return wgpu::TextureFormat::BC7RGBAUnorm;
}
}
struct TextureFormatInfo {
uint8_t blockWidth;
uint8_t blockHeight;
@ -55,10 +38,19 @@ static wgpu::Extent3D physical_size(wgpu::Extent3D size, TextureFormatInfo info)
return {width, height, size.depthOrArrayLayers};
}
TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mips, TextureFormat format,
TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mips, metaforce::ETexelFormat format,
ArrayRef<uint8_t> data, zstring_view label) noexcept {
auto handle = new_dynamic_texture_2d(width, height, mips, format, label);
const TextureRef& ref = *handle.ref;
ByteBuffer buffer;
if (ref.gameFormat != metaforce::ETexelFormat::Invalid) {
buffer = convert_texture(ref.gameFormat, ref.size.width, ref.size.height, ref.mipCount, data);
if (!buffer.empty()) {
data = {buffer.data(), buffer.size()};
}
}
uint32_t offset = 0;
for (uint32_t mip = 0; mip < mips; ++mip) {
const auto mipSize = wgpu::Extent3D{
@ -95,7 +87,7 @@ TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mi
return handle;
}
TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, TextureFormat format,
TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, metaforce::ETexelFormat format,
zstring_view label) noexcept {
const auto wgpuFormat = to_wgpu(format);
const auto size = wgpu::Extent3D{
@ -118,7 +110,7 @@ TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t m
};
auto texture = g_device.CreateTexture(&textureDescriptor);
auto textureView = texture.CreateView(&textureViewDescriptor);
return {std::make_shared<TextureRef>(std::move(texture), std::move(textureView), size, wgpuFormat)};
return {std::make_shared<TextureRef>(std::move(texture), std::move(textureView), size, wgpuFormat, mips, format)};
}
TextureHandle new_render_texture(uint32_t width, uint32_t height, uint32_t color_bind_count, uint32_t depth_bind_count,
@ -129,6 +121,15 @@ TextureHandle new_render_texture(uint32_t width, uint32_t height, uint32_t color
// TODO accept mip/layer parameters
void write_texture(const TextureHandle& handle, ArrayRef<uint8_t> data) noexcept {
const TextureRef& ref = *handle.ref;
ByteBuffer buffer;
if (ref.gameFormat != metaforce::ETexelFormat::Invalid) {
buffer = convert_texture(ref.gameFormat, ref.size.width, ref.size.height, ref.mipCount, data);
if (!buffer.empty()) {
data = {buffer.data(), buffer.size()};
}
}
const auto dstView = wgpu::ImageCopyTexture{
.texture = ref.texture,
};

View File

@ -0,0 +1,536 @@
#include "texture_convert.hpp"
namespace aurora::gfx {
static logvisor::Module Log("aurora::gfx");
struct RGBA8 {
u8 r;
u8 g;
u8 b;
u8 a;
};
struct DXT1Block {
u16 color1;
u16 color2;
std::array<u8, 4> lines;
};
/* GX uses this upsampling technique to extract full 8-bit range */
constexpr u8 Convert3To8(u8 v) {
/* Swizzle bits: 00000123 -> 12312312 */
return static_cast<u8>((u32{v} << 5) | (u32{v} << 2) | (u32{v} >> 1));
}
constexpr u8 Convert4To8(u8 v) {
/* Swizzle bits: 00001234 -> 12341234 */
return static_cast<u8>((u32{v} << 4) | u32{v});
}
constexpr u8 Convert5To8(u8 v) {
/* Swizzle bits: 00012345 -> 12345123 */
return static_cast<u8>((u32{v} << 3) | (u32{v} >> 2));
}
constexpr u8 Convert6To8(u8 v) {
/* Swizzle bits: 00123456 -> 12345612 */
return static_cast<u8>((u32{v} << 2) | (u32{v} >> 4));
}
static size_t ComputeMippedTexelCount(u32 w, u32 h, u32 mips) {
size_t ret = w * h;
for (u32 i = mips; i > 1; --i) {
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
ret += w * h;
}
return ret;
}
static size_t ComputeMippedBlockCountDXT1(u32 w, u32 h, u32 mips) {
w /= 4;
h /= 4;
size_t ret = w * h;
for (u32 i = mips; i > 1; --i) {
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
ret += w * h;
}
return ret;
}
static ByteBuffer BuildI4FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data) {
const size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
auto* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const uint8_t* in = data.data();
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 7) / 8;
const uint32_t bheight = (h + 7) / 8;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 8;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 8;
for (uint32_t y = 0; y < std::min(h, 8u); ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (uint32_t x = 0; x < std::min(w, 8u); ++x) {
target[x].r = Convert4To8(in[x / 2] >> ((x & 1) ? 0 : 4) & 0xf);
target[x].g = target[x].r;
target[x].b = target[x].r;
target[x].a = target[x].r;
}
in += std::min<size_t>(w / 4, 4);
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
static ByteBuffer BuildI8FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data) {
const size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
auto* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const uint8_t* in = data.data();
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 7) / 8;
const uint32_t bheight = (h + 3) / 4;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 4;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 8;
for (uint32_t y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
const auto n = std::min(w, 8u);
for (size_t x = 0; x < n; ++x) {
const auto v = in[x];
target[x].r = v;
target[x].g = v;
target[x].b = v;
target[x].a = v;
}
in += n;
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
ByteBuffer BuildIA4FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data) {
const size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
RGBA8* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const uint8_t* in = data.data();
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 7) / 8;
const uint32_t bheight = (h + 3) / 4;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 4;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 8;
for (uint32_t y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
const auto n = std::min(w, 8u);
for (size_t x = 0; x < n; ++x) {
const u8 intensity = Convert4To8(in[x] >> 4 & 0xf);
target[x].r = intensity;
target[x].g = intensity;
target[x].b = intensity;
target[x].a = Convert4To8(in[x] & 0xf);
}
in += n;
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
ByteBuffer BuildIA8FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data) {
const size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
auto* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const auto* in = reinterpret_cast<const uint16_t*>(data.data());
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 3) / 4;
const uint32_t bheight = (h + 3) / 4;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 4;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 4;
for (uint32_t y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (size_t x = 0; x < 4; ++x) {
const u8 intensity = in[x] >> 8;
target[x].r = intensity;
target[x].g = intensity;
target[x].b = intensity;
target[x].a = in[x] & 0xff;
}
in += 4;
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
ByteBuffer BuildC4FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data, RGBA8* palette) {
const size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
auto* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const uint8_t* in = data.data();
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 7) / 8;
const uint32_t bheight = (h + 7) / 8;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 8;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 8;
for (uint32_t y = 0; y < 8; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
const auto n = std::min(w, 8u);
for (size_t x = 0; x < n; ++x) {
target[x] = palette[in[x / 2] >> ((x & 1) ? 0 : 4) & 0xf];
}
in += n;
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
ByteBuffer BuildC8FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data, RGBA8* palette) {
const size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
auto* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const uint8_t* in = data.data();
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 7) / 8;
const uint32_t bheight = (h + 3) / 4;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 4;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 8;
for (uint32_t y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
const auto n = std::min(w, 8u);
for (size_t x = 0; x < n; ++x) {
target[x] = palette[in[x]];
}
in += n;
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
ByteBuffer BuildRGB565FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data) {
const size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
auto* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const auto* in = reinterpret_cast<const uint16_t*>(data.data());
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 3) / 4;
const uint32_t bheight = (h + 3) / 4;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 4;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 4;
for (uint32_t y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (size_t x = 0; x < 4; ++x) {
const auto texel = in[x];
target[x].r = Convert5To8(texel >> 11 & 0x1f);
target[x].g = Convert6To8(texel >> 5 & 0x3f);
target[x].b = Convert5To8(texel & 0x1f);
target[x].a = 0xff;
}
in += 4;
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
ByteBuffer BuildRGB5A3FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data) {
size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
auto* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const auto* in = reinterpret_cast<const uint16_t*>(data.data());
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 3) / 4;
const uint32_t bheight = (h + 3) / 4;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 4;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 4;
for (uint32_t y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (size_t x = 0; x < 4; ++x) {
const auto texel = in[x];
if ((texel & 0x8000) != 0) {
target[x].r = Convert5To8(texel >> 10 & 0x1f);
target[x].g = Convert5To8(texel >> 5 & 0x1f);
target[x].b = Convert5To8(texel & 0x1f);
target[x].a = 0xff;
} else {
target[x].r = Convert4To8(texel >> 8 & 0xf);
target[x].g = Convert4To8(texel >> 4 & 0xf);
target[x].b = Convert4To8(texel & 0xf);
target[x].a = Convert3To8(texel >> 12 & 0x7);
}
}
in += 4;
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
ByteBuffer BuildRGBA8FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data) {
const size_t texelCount = ComputeMippedTexelCount(width, height, mips);
ByteBuffer buf{sizeof(RGBA8) * texelCount};
uint32_t w = width;
uint32_t h = height;
auto* targetMip = reinterpret_cast<RGBA8*>(buf.data());
const uint8_t* in = data.data();
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 3) / 4;
const uint32_t bheight = (h + 3) / 4;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 4;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 4;
for (uint32_t c = 0; c < 2; ++c) {
for (uint32_t y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (size_t x = 0; x < 4; ++x) {
if (c != 0) {
target[x].g = in[x * 2];
target[x].b = in[x * 2 + 1];
} else {
target[x].a = in[x * 2];
target[x].r = in[x * 2 + 1];
}
}
in += 8;
}
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
template <typename T>
constexpr T bswap16(T val) noexcept {
#if __GNUC__
return __builtin_bswap16(val);
#elif _WIN32
return _byteswap_ushort(val);
#else
return (val = (val << 8) | ((val >> 8) & 0xFF));
#endif
}
ByteBuffer BuildDXT1FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef<uint8_t> data) {
const size_t blockCount = ComputeMippedBlockCountDXT1(width, height, mips);
ByteBuffer buf{sizeof(DXT1Block) * blockCount};
uint32_t w = width / 4;
uint32_t h = height / 4;
auto* targetMip = reinterpret_cast<DXT1Block*>(buf.data());
const auto* in = reinterpret_cast<const DXT1Block*>(data.data());
for (uint32_t mip = 0; mip < mips; ++mip) {
const uint32_t bwidth = (w + 1) / 2;
const uint32_t bheight = (h + 1) / 2;
for (uint32_t by = 0; by < bheight; ++by) {
const uint32_t baseY = by * 2;
for (uint32_t bx = 0; bx < bwidth; ++bx) {
const uint32_t baseX = bx * 2;
for (uint32_t y = 0; y < 2; ++y) {
DXT1Block* target = targetMip + (baseY + y) * w + baseX;
for (size_t x = 0; x < 2; ++x) {
target[x].color1 = bswap16(in[x].color1);
target[x].color2 = bswap16(in[x].color2);
for (size_t i = 0; i < 4; ++i) {
std::array<uint8_t, 4> ind;
const uint8_t packed = in[x].lines[i];
ind[3] = packed & 0x3;
ind[2] = (packed >> 2) & 0x3;
ind[1] = (packed >> 4) & 0x3;
ind[0] = (packed >> 6) & 0x3;
target[x].lines[i] = ind[0] | (ind[1] << 2) | (ind[2] << 4) | (ind[3] << 6);
}
}
in += 2;
}
}
}
targetMip += w * h;
if (w > 1) {
w /= 2;
}
if (h > 1) {
h /= 2;
}
}
return buf;
}
ByteBuffer convert_texture(metaforce::ETexelFormat format, uint32_t width, uint32_t height, uint32_t mips,
ArrayRef<uint8_t> data) {
switch (format) {
case metaforce::ETexelFormat::RGBA8PC:
case metaforce::ETexelFormat::R8PC:
return {};
case metaforce::ETexelFormat::Invalid:
Log.report(logvisor::Fatal, FMT_STRING("convert_texture: invalid format supplied"));
unreachable();
case metaforce::ETexelFormat::I4:
return BuildI4FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::I8:
return BuildI8FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::IA4:
return BuildIA4FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::IA8:
return BuildIA8FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::C4:
Log.report(logvisor::Fatal, FMT_STRING("convert_texture: C4 unimplemented"));
unreachable();
// return BuildC4FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::C8:
Log.report(logvisor::Fatal, FMT_STRING("convert_texture: C8 unimplemented"));
unreachable();
// return BuildC8FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::C14X2:
Log.report(logvisor::Fatal, FMT_STRING("convert_texture: C14X2 unimplemented"));
unreachable();
case metaforce::ETexelFormat::RGB565:
return BuildRGB565FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::RGB5A3:
return BuildRGB5A3FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::RGBA8:
return BuildRGBA8FromGCN(width, height, mips, data);
case metaforce::ETexelFormat::CMPR:
if (gpu::g_device.HasFeature(wgpu::FeatureName::TextureCompressionBC)) {
return BuildDXT1FromGCN(width, height, mips, data);
} else {
Log.report(logvisor::Fatal, FMT_STRING("convert_texture: TODO implement CMPR to RGBA"));
unreachable();
}
}
}
} // namespace aurora::gfx

View File

@ -0,0 +1,25 @@
#pragma once
#include "common.hpp"
#include "../gpu.hpp"
namespace aurora::gfx {
static wgpu::TextureFormat to_wgpu(metaforce::ETexelFormat format) {
switch (format) {
case metaforce::ETexelFormat::C8:
case metaforce::ETexelFormat::R8PC:
return wgpu::TextureFormat::R8Unorm;
case metaforce::ETexelFormat::CMPR:
if (gpu::g_device.HasFeature(wgpu::FeatureName::TextureCompressionBC)) {
return wgpu::TextureFormat::BC1RGBAUnorm;
}
[[fallthrough]];
default:
return wgpu::TextureFormat::RGBA8Unorm;
}
}
ByteBuffer convert_texture(metaforce::ETexelFormat format, uint32_t width, uint32_t height, uint32_t mips,
ArrayRef<uint8_t> data);
} // namespace aurora::gfx

View File

@ -31,12 +31,12 @@ void ImGuiEngine_Initialize(float scale) {
ImGuiIO& io = ImGui::GetIO();
io.Fonts->Clear();
auto* fontData = new uint8_t[NOTO_MONO_FONT_DECOMPRESSED_SZ];
auto* fontData = ImGui::MemAlloc(NOTO_MONO_FONT_DECOMPRESSED_SZ);
{
auto stream = std::make_unique<metaforce::CMemoryInStream>(
static_cast<const u8*>(NOTO_MONO_FONT), NOTO_MONO_FONT_SZ, metaforce::CMemoryInStream::EOwnerShip::NotOwned);
metaforce::CZipInputStream zipInputStream{std::move(stream)};
zipInputStream.Get(fontData, NOTO_MONO_FONT_DECOMPRESSED_SZ);
zipInputStream.Get(static_cast<uint8_t*>(fontData), NOTO_MONO_FONT_DECOMPRESSED_SZ);
}
ImFontConfig fontConfig{};