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 IObjectStore.hpp
CSimplePool.hpp CSimplePool.cpp CSimplePool.hpp CSimplePool.cpp
CGameOptions.hpp CGameOptions.cpp CGameOptions.hpp CGameOptions.cpp
CGameOptionsTouchBar.hpp CGameOptionsTouchBar.cpp
CStaticInterference.hpp CStaticInterference.cpp CStaticInterference.hpp CStaticInterference.cpp
CCRC32.hpp CCRC32.cpp CCRC32.hpp CCRC32.cpp
IFactory.hpp IFactory.hpp

View File

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

View File

@ -115,7 +115,7 @@ public:
CAssetId x0_id; CAssetId x0_id;
kabufuda::EAnimationSpeed x4_speed; kabufuda::EAnimationSpeed x4_speed;
TLockedToken<CTexture> x8_tex; 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 }; enum class EStatus { Standby, Transferring, Done };
@ -131,8 +131,6 @@ public:
std::vector<u8> xf4_saveBuffer; std::vector<u8> xf4_saveBuffer;
std::vector<u8> x104_cardBuffer; 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) {} CCardFileInfo(kabufuda::ECardSlot port, std::string_view name) : m_handle(port), x18_fileName(name) {}
void LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp); void LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp);

View File

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

View File

@ -14,71 +14,6 @@ class CCubeModel;
class CCubeSurface; class CCubeSurface;
struct CModelFlags; 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 { enum class CCubeMaterialFlagBits : u32 {
fKonstValues = 0x8, fKonstValues = 0x8,
fDepthSorting = 0x10, fDepthSorting = 0x10,

View File

@ -64,11 +64,11 @@ private:
std::optional<CPVSVisSet> xc8_pvs; std::optional<CPVSVisSet> xc8_pvs;
bool xdc_{}; bool xdc_{};
u32 xe0_pvsAreaIdx = UINT32_MAX; 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; std::unique_ptr<CTexture> x14c_reflectionTex;
CTexture x150_reflectionTex{ETexelFormat::IA8, 32, 32, 1}; CTexture x150_reflectionTex{ETexelFormat::IA8, 32, 32, 1, "Reflection Texture"};
CTexture x1b8_fogVolumeRamp{ETexelFormat::I8, 256, 256, 1}; CTexture x1b8_fogVolumeRamp{ETexelFormat::I8, 256, 256, 1, "Fog Volume Ramp Texture"};
CTexture x220_sphereRamp{ETexelFormat::I8, 32, 32, 1}; CTexture x220_sphereRamp{ETexelFormat::I8, 32, 32, 1, "Sphere Ramp Texture"};
// CGraphicsPalette x288_thermoPalette{1, 16}; // CGraphicsPalette x288_thermoPalette{1, 16};
CRandom16 x2a8_thermalRand{20}; CRandom16 x2a8_thermalRand{20};
std::list<CFogVolumeListItem> x2ac_fogVolumes; 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) { CFont::CFont(float scale) : x0_fontSize(16.f * scale), x4_scale(scale) {
if (sNumInstances == 0) { if (sNumInstances == 0) {
mpTexture = std::make_unique<CTexture>(ETexelFormat::I8, 256, 256, 1); mpTexture = std::make_unique<CTexture>(ETexelFormat::I8, 256, 256, 1, "Font Texture");
u8* fontData = new u8[(mpTexture->GetBitsPerPixel() * mpTexture->GetWidth() * mpTexture->GetHeight()) / 8]; u8* fontData = new u8[(mpTexture->GetBitDepth() * mpTexture->GetWidth() * mpTexture->GetHeight()) / 8];
memcpy(fontData, sSystemFont.data(), sSystemFont.size()); memcpy(fontData, sSystemFont.data(), sSystemFont.size());
// u8* textureData = mpTexture->GetBitMapData(); // u8* textureData = mpTexture->GetBitMapData();
// LinearToTile8(textureData, fontData); // 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; } void CGraphics::SetIsBeginSceneClearFb(bool clear) { g_IsBeginSceneClearFb = clear; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a564c{ // Stream API
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC}, static EStreamFlags sStreamFlags;
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA}, static zeus::CColor sQueuedColor;
}; static zeus::CVector2f sQueuedTexCoord;
static zeus::CVector3f sQueuedNormal;
const CTevCombiners::CTevPass CGraphics::sTevPass805a5698{ void CGraphics::SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass) {
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_C0, GX::TevColorArg::CC_ZERO}, CTevCombiners::SetupPass(stage, pass);
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_A0, GX::TevAlphaArg::CA_ZERO}, }
};
const CTevCombiners::CTevPass CGraphics::sTevPass805a5e70{ void CGraphics::StreamBegin(GX::Primitive primitive) {
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_C0}, sStreamFlags = {};
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_A0}, aurora::gfx::stream_begin(primitive);
}; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a5ebc{ void CGraphics::StreamNormal(const zeus::CVector3f& nrm) {
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_ZERO}, sQueuedNormal = nrm;
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_ZERO}, sStreamFlags |= EStreamFlagBits::fHasNormal;
}; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a5f08{ void CGraphics::StreamColor(float r, float g, float b, float a) {
{GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_TEXA, GX::TevColorArg::CC_ZERO}, sQueuedColor = zeus::CColor{r, g, b, a};
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA}, sStreamFlags |= EStreamFlagBits::fHasColor;
}; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a5f54{ void CGraphics::StreamColor(const zeus::CColor& color) {
{GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ONE, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_ZERO}, sQueuedColor = color;
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO}, sStreamFlags |= EStreamFlagBits::fHasColor;
}; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a5fa0{ void CGraphics::StreamTexcoord(float x, float y) {
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC}, sQueuedTexCoord = {x, y};
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA}, sStreamFlags |= EStreamFlagBits::fHasTexture;
}; }
const CTevCombiners::CTevPass CGraphics::sTevPass804bfcc0{ void CGraphics::StreamTexcoord(const zeus::CVector2f& uv) {
{GX::TevColorArg::CC_C0, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO}, sQueuedTexCoord = uv;
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA}, sStreamFlags |= EStreamFlagBits::fHasTexture;
}; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a5fec{ void CGraphics::StreamVertex(float xyz) {
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC}, const zeus::CVector3f pos{xyz, xyz, xyz};
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO}, aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
}; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a6038{ void CGraphics::StreamVertex(float x, float y, float z) {
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO}, const zeus::CVector3f pos{x, y, z};
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_KONST, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO}, aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
}; }
const CTevCombiners::CTevPass CGraphics::sTevPass805a6084{ void CGraphics::StreamVertex(const zeus::CVector3f& pos) {
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_CPREV, GX::TevColorArg::CC_APREV, GX::TevColorArg::CC_ZERO}, aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_APREV}, }
};
void CGraphics::StreamEnd() {
aurora::gfx::stream_end();
}
} // namespace metaforce } // namespace metaforce

View File

@ -1,23 +1,21 @@
#pragma once #pragma once
#include "Runtime/RetroTypes.hpp"
#include "Runtime/Graphics/GX.hpp"
#include "Runtime/Graphics/CTevCombiners.hpp"
#include "Runtime/ConsoleVariables/CVar.hpp"
#include <array> #include <array>
#include <chrono> #include <chrono>
#include <vector> #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/CColor.hpp>
#include <zeus/CTransform.hpp> #include <zeus/CTransform.hpp>
#include <zeus/CVector2f.hpp> #include <zeus/CVector2f.hpp>
#include <zeus/CVector2i.hpp> #include <zeus/CVector2i.hpp>
#include <aurora/gfx.hpp> #include <aurora/gfx.hpp>
#include <optick.h>
using frame_clock = std::chrono::high_resolution_clock; 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_FAR 1.f
#define DEPTH_SKY 0.999f #define DEPTH_SKY 0.999f
#define DEPTH_TARGET_MANAGER 0.12500012f #define DEPTH_TARGET_MANAGER 0.12500012f
@ -124,47 +103,6 @@ enum class ETexelFormat {
#define CUBEMAP_RES 256 #define CUBEMAP_RES 256
#define CUBEMAP_MIPS 6 #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 { class CGraphics {
public: public:
struct CProjectionState { struct CProjectionState {
@ -352,26 +290,17 @@ public:
// static void DrawArray(size_t start, size_t count) { g_BooMainCommandQueue->draw(start, count); } // 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 void DrawArrayIndexed(size_t start, size_t count) { g_BooMainCommandQueue->drawIndexed(start, count); }
static const CTevCombiners::CTevPass sTevPass805a564c; static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass);
static const CTevCombiners::CTevPass sTevPass805a5698; static void StreamBegin(GX::Primitive primitive);
static void StreamNormal(const zeus::CVector3f& nrm);
static const CTevCombiners::CTevPass sTevPass805a5e70; static void StreamColor(float r, float g, float b, float a);
static void StreamColor(const zeus::CColor& color);
static const CTevCombiners::CTevPass sTevPass805a5ebc; static void StreamTexcoord(float x, float y);
static void StreamTexcoord(const zeus::CVector2f& uv);
static const CTevCombiners::CTevPass sTevPass805a5f08; static void StreamVertex(float xyz);
static void StreamVertex(float x, float y, float z);
static const CTevCombiners::CTevPass sTevPass805a5f54; static void StreamVertex(const zeus::CVector3f& pos);
static void StreamEnd();
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;
}; };
template <class VTX> template <class VTX>

View File

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

View File

@ -10,8 +10,8 @@ set(GRAPHICS_SOURCES
CLineRenderer.hpp CLineRenderer.cpp CLineRenderer.hpp CLineRenderer.cpp
CMetroidModelInstance.cpp CMetroidModelInstance.hpp CMetroidModelInstance.cpp CMetroidModelInstance.hpp
CLight.hpp CLight.cpp CLight.hpp CLight.cpp
DolphinCTexture.hpp DolphinCTexture.cpp CTevCombiners.cpp CTevCombiners.hpp
CTexture.hpp CTextureBoo.cpp CTexture.hpp CTexture.cpp
CModel.cpp CModel.hpp CModel.cpp CModel.hpp
CSkinnedModel.hpp CSkinnedModel.cpp CSkinnedModel.hpp CSkinnedModel.cpp
CVertexMorphEffect.hpp CVertexMorphEffect.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 "Audio/g721.h"
#include "Runtime/CDvdRequest.hpp" #include "CDvdRequest.hpp"
#include "Runtime/Graphics/CGraphics.hpp" #include "Graphics/CGraphics.hpp"
#include "Graphics/CCubeRenderer.hpp"
#include "GameGlobalObjects.hpp"
#include <amuse/DSPCodec.hpp> #include <amuse/DSPCodec.hpp>
#include <turbojpeg.h> #include <turbojpeg.h>
@ -190,29 +192,28 @@ CMoviePlayer::CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bo
CTHPTextureSet& set = x80_textures.emplace_back(); CTHPTextureSet& set = x80_textures.emplace_back();
if (deinterlace) { if (deinterlace) {
/* metaforce addition: this way interlaced THPs don't look horrible */ /* 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, set.Y[0] =
aurora::gfx::TextureFormat::R8, 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)); 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, set.Y[1] =
aurora::gfx::TextureFormat::R8, 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)); 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, set.U =
aurora::gfx::TextureFormat::R8, 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)); 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, set.V =
aurora::gfx::TextureFormat::R8, 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)); fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i));
} else { } else {
/* normal progressive presentation */ /* normal progressive presentation */
set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height, 1, set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height, 1, ETexelFormat::R8PC,
aurora::gfx::TextureFormat::R8,
fmt::format(FMT_STRING("Movie {} Texture Set {} Y"), path, i)); 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, set.U =
aurora::gfx::TextureFormat::R8, 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)); 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, set.V =
aurora::gfx::TextureFormat::R8, 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)); fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i));
} }
if (xf4_25_hasAudio) if (xf4_25_hasAudio)
set.audioBuf.reset(new s16[x28_thpHead.maxAudioSamples * 2]); set.audioBuf.reset(new s16[x28_thpHead.maxAudioSamples * 2]);
@ -364,20 +365,37 @@ void CMoviePlayer::Rewind() {
xe8_curSeconds = 0.f; xe8_curSeconds = 0.f;
} }
void CMoviePlayer::SetFrame(float hpad, float vpad) { void CMoviePlayer::Draw() {
m_hpad = hpad; if (GetIsFullyCached()) {
m_vpad = vpad; 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) if (xd0_drawTexSlot == UINT32_MAX)
return; return;
SCOPED_GRAPHICS_DEBUG_GROUP("CMoviePlayer::DrawFrame", zeus::skYellow); SCOPED_GRAPHICS_DEBUG_GROUP("CMoviePlayer::DrawFrame", zeus::skYellow);
/* draw appropriate field */ /* draw appropriate field */
CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot]; 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, aurora::gfx::queue_movie_player(tex.Y[m_deinterlace ? (xfc_fieldIndex != 0) : 0], tex.U, tex.V, v1, v2, v3, v4);
m_vpad);
/* ensure second field is being displayed by VI to signal advance /* ensure second field is being displayed by VI to signal advance
* (faked in metaforce with continuous xor) */ * (faked in metaforce with continuous xor) */

View File

@ -109,10 +109,14 @@ private:
float m_hpad; float m_hpad;
float m_vpad; float m_vpad;
static u32 THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo);
void DecodeFromRead(const void* data); 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 PostDVDReadRequestIfNeeded();
void ReadCompleted();
static u32 THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo);
public: public:
CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bool deinterlace); CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bool deinterlace);
@ -135,8 +139,7 @@ public:
float GetPlayedSeconds() const { return xdc_frameRem + xe8_curSeconds; } float GetPlayedSeconds() const { return xdc_frameRem + xe8_curSeconds; }
float GetTotalSeconds() const { return xe4_totalSeconds; } float GetTotalSeconds() const { return xe4_totalSeconds; }
void SetPlayMode(EPlayMode mode) { xe0_playMode = mode; } void SetPlayMode(EPlayMode mode) { xe0_playMode = mode; }
void SetFrame(float hpad, float vpad); void Draw();
void DrawFrame();
void Update(float dt); void Update(float dt);
std::pair<u32, u32> GetVideoDimensions() const { return {x6c_videoInfo.width, x6c_videoInfo.height}; } 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 "CToken.hpp"
#include "zeus/Math.hpp"
#include <zeus/Math.hpp>
#include <magic_enum.hpp>
u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, bool mipmap, u8 max_lod) { u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, bool mipmap, u8 max_lod) {
s32 shiftX = 0; s32 shiftX = 0;
@ -70,30 +72,29 @@ u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, bool mipmap, u8 max_lo
return bufLen; return bufLen;
} }
namespace metaforce::WIP {
namespace { namespace metaforce {
static std::array<CTexture*, GX::MAX_TEXMAP> sLoadedTextures{}; 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) : x0_fmt(fmt)
, x4_w(w) , x4_w(w)
, x6_h(h) , x6_h(h)
, x8_mips(mips) , x8_mips(mips)
, x9_bitsPerPixel(TexelFormatBitsPerPixel(fmt)) , 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); InitBitmapBuffers(fmt, w, h, mips);
InitTextureObjs(); InitTextureObjs(false);
} }
CTexture::CTexture(CInputStream& in, EAutoMipmap automip, EBlackKey blackKey) { CTexture::CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip, EBlackKey blackKey)
x64_frameAllocated = sCurrentFrameCount; : x0_fmt(ETexelFormat(in.ReadLong()))
x0_fmt = ETexelFormat(in.ReadLong()); , x4_w(in.ReadShort())
x4_w = in.ReadShort(); , x6_h(in.ReadShort())
x6_h = in.ReadShort(); , x8_mips(in.ReadLong())
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); bool hasPalette = (x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2);
if (hasPalette) { if (hasPalette) {
x10_graphicsPalette = std::make_unique<CGraphicsPalette>(in); 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; xa_24_locked = true;
return GetBitMapData(0); return GetBitMapData(0);
} }
@ -141,7 +142,8 @@ void CTexture::UnLock() {
CountMemory(); CountMemory();
// DCFlushRange(x44_aramToken.GetMRAMSafe(), ROUND_UP_32(xc_memoryAllocated)); // 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) { if (sLoadedTextures[id] != this || xa_29_canLoadObj) {
auto* image_ptr = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get(); auto* image_ptr = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get();
CountMemory(); CountMemory();
@ -161,8 +163,8 @@ void CTexture::Load(GX::TexMapID id, CTexture::EClampMode clamp) {
x64_frameAllocated = sCurrentFrameCount; 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(); auto image_ptr = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get();
u32 width = x4_w; u32 width = x4_w;
u32 height = x6_h; u32 height = x6_h;
@ -196,7 +198,7 @@ void CTexture::MakeSwappable() {
xa_27_noSwap = false; xa_27_noSwap = false;
} }
const void* CTexture::GetConstBitMapData(s32 mip) const { const u8* CTexture::GetConstBitMapData(s32 mip) const {
u32 buffOffset = 0; u32 buffOffset = 0;
if (x8_mips > 0) { if (x8_mips > 0) {
for (u32 i = 0; i < x8_mips; ++i) { 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*/ 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) { switch (fmt) {
case ETexelFormat::I4: case ETexelFormat::I4:
x18_gxFormat = GX::TF_I4; x18_gxFormat = GX::TF_I4;
@ -252,11 +254,12 @@ void CTexture::InitBitmapBuffers(ETexelFormat fmt, s16 width, s16 height, s32 mi
: x18_gxFormat; : x18_gxFormat;
xc_memoryAllocated = GXGetTexBufferSize(width, height, format, mips > 1, mips > 1 ? 11 : 0); 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);*/ /*x44_aramToken.PostConstruct(buf, xc_memoryAllocated, 1);*/
CountMemory(); CountMemory();
} }
void CTexture::InitTextureObjs() {
void CTexture::InitTextureObjs(bool write) {
xa_26_isPowerOfTwo = zeus::floorPowerOfTwo(x4_w) == x4_w && zeus::floorPowerOfTwo(x6_h) == x6_h; xa_26_isPowerOfTwo = zeus::floorPowerOfTwo(x4_w) == x4_w && zeus::floorPowerOfTwo(x6_h) == x6_h;
if (!xa_26_isPowerOfTwo) { if (!xa_26_isPowerOfTwo) {
@ -267,12 +270,17 @@ void CTexture::InitTextureObjs() {
if (IsCITexture()) { if (IsCITexture()) {
// GXInitTexObjCI(x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat, u32(x40_clampMode), // GXInitTexObjCI(x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat, u32(x40_clampMode),
// u32(x40_clampMode), x8_mips > 1, 0); // u32(x40_clampMode), x8_mips > 1, 0);
// TODO
} else { } else {
// GXInitTexObj(x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat, u32(x40_clampMode), // GXInitTexObj(x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat, u32(x40_clampMode),
// u32(x40_clampMode), x8_mips > 1); // 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, // GXInitTexObjLOD(x20_texObj, x8_mips > 1 ? GX_LIN_MIP_LIN : GX_LINEAR, 0.f, static_cast<float>(x8_mips) - 1.f,
// 0.f, // 0.f,
// false, false, x8_mips > 1 ? GX_ANISO_4 : GX_ANISO_1); // 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; xa_29_canLoadObj = true;
} }
@ -325,12 +333,11 @@ bool CTexture::sMangleMips = false;
u32 CTexture::sCurrentFrameCount = 0; u32 CTexture::sCurrentFrameCount = 0;
u32 CTexture::sTotalAllocatedMemory = 0; u32 CTexture::sTotalAllocatedMemory = 0;
void CTexture::InvalidateTexMap(GX::TexMapID id) { void CTexture::InvalidateTexMap(GX::TexMapID id) { sLoadedTextures[id] = nullptr; }
sLoadedTextures[id] = nullptr;
}
CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
CObjectReference* selfRef) { 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 #pragma once
#include <memory>
#include <string>
#include "Runtime/CFactoryMgr.hpp" #include "Runtime/CFactoryMgr.hpp"
#include "Runtime/GCNTypes.hpp"
#include "Runtime/Graphics/CGraphics.hpp" #include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/IObj.hpp"
#include "Runtime/Streams/IOStreams.hpp"
#include "Runtime/Graphics/CGraphicsPalette.hpp" #include "Runtime/Graphics/CGraphicsPalette.hpp"
#include "Runtime/Graphics/GX.hpp"
#include "Runtime/IObj.hpp"
#include "Runtime/Streams/CInputStream.hpp"
namespace metaforce { namespace metaforce {
class CVParamTransfer;
class CTextureInfo;
class CTexture { class CTexture {
class CDumpedBitmapDataReloader { class CDumpedBitmapDataReloader {
int x0_; int x0_;
@ -26,12 +20,13 @@ class CTexture {
}; };
public: public:
enum class EClampMode { enum class EAutoMipmap {
Clamp, Zero,
Repeat, One,
Mirror,
}; };
enum class EBlackKey { Zero, One };
enum class EFontType { enum class EFontType {
None = -1, None = -1,
OneLayer = 0, /* Fill bit0 */ OneLayer = 0, /* Fill bit0 */
@ -43,74 +38,77 @@ public:
}; };
private: private:
static bool sMangleMips;
static u32 sCurrentFrameCount; static u32 sCurrentFrameCount;
ETexelFormat x0_fmt; static u32 sTotalAllocatedMemory;
u16 x4_w;
u16 x6_h; ETexelFormat x0_fmt = ETexelFormat::Invalid;
u8 x8_mips; u16 x4_w = 0;
u8 x9_bitsPerPixel; u16 x6_h = 0;
u32 xc_memoryAllocated{}; 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<CGraphicsPalette> x10_graphicsPalette;
std::unique_ptr<CDumpedBitmapDataReloader> x14_bitmapReloader; std::unique_ptr<CDumpedBitmapDataReloader> x14_bitmapReloader;
u32 x18_gxFormat{}; u32 x18_gxFormat = GX::TF_RGB565;
u32 x1c_gxCIFormat{}; u32 x1c_gxCIFormat = GX::TF_C8;
/* GXTexObj x20_texObj */ aurora::gfx::TextureHandle x20_texObj; // was GXTexObj
EClampMode x40_clampMode = EClampMode::Repeat; EClampMode x40_clampMode = EClampMode::Repeat;
/* CARAMToken x44_aramToken */ std::unique_ptr<u8[]> x44_aramToken_x4_buff; // was CARAMToken
u32 x64_frameAllocated{}; u32 x64_frameAllocated{};
aurora::gfx::TextureHandle m_tex; // Metaforce additions
aurora::gfx::TextureHandle m_paletteTex; std::string m_label;
std::unique_ptr<u8[]> m_otex;
EFontType m_ftype = EFontType::None;
const CTextureInfo* m_textureInfo{};
size_t ComputeMippedTexelCount() const; void InitBitmapBuffers(ETexelFormat fmt, u16 width, u16 height, s32 mips);
size_t ComputeMippedBlockCountDXT1() const; void InitTextureObjs(bool write); // write param is added
void BuildI4FromGCN(CInputStream& in, aurora::zstring_view label); void CountMemory();
void BuildI8FromGCN(CInputStream& in, aurora::zstring_view label); void UncountMemory();
void BuildIA4FromGCN(CInputStream& in, aurora::zstring_view label); void MangleMipmap(u32 mip);
void BuildIA8FromGCN(CInputStream& in, aurora::zstring_view label); static u32 TexelFormatBitsPerPixel(ETexelFormat fmt);
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: public:
CTexture(ETexelFormat, s16, s16, s32); // Label parameters are new for Metaforce
CTexture(std::unique_ptr<u8[]>&& in, u32 length, bool otex, const CTextureInfo* inf, CAssetId id); CTexture(ETexelFormat fmt, u16 w, u16 h, s32 mips, std::string_view label);
[[nodiscard]] ETexelFormat GetTexelFormat() const { return x0_fmt; } CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip = EAutoMipmap::Zero,
[[nodiscard]] ETexelFormat GetMemoryCardTexelFormat() const { EBlackKey blackKey = EBlackKey::Zero);
return x0_fmt == ETexelFormat::C8PC ? ETexelFormat::C8 : ETexelFormat::RGB5A3;
} [[nodiscard]] ETexelFormat GetTextureFormat() const { return x0_fmt; }
[[nodiscard]] u16 GetWidth() const { return x4_w; } [[nodiscard]] u16 GetWidth() const { return x4_w; }
[[nodiscard]] u16 GetHeight() const { return x6_h; } [[nodiscard]] u16 GetHeight() const { return x6_h; }
[[nodiscard]] u8 GetNumMips() const { return x8_mips; } [[nodiscard]] u8 GetNumberOfMipMaps() const { return x8_mips; }
[[nodiscard]] u8 GetBitsPerPixel() const { return x9_bitsPerPixel; } [[nodiscard]] u32 GetBitDepth() const { return x9_bitsPerPixel; }
void Load(int slot, EClampMode clamp) const; [[nodiscard]] u32 GetMemoryAllocated() const { return xc_memoryAllocated; }
[[nodiscard]] const aurora::gfx::TextureHandle& GetTexture() const { return m_tex; } [[nodiscard]] const std::unique_ptr<CGraphicsPalette>& GetPalette() const { return x10_graphicsPalette; }
[[nodiscard]] const aurora::gfx::TextureHandle& GetPaletteTexture() const { return m_paletteTex; } [[nodiscard]] bool HasPalette() const { return x10_graphicsPalette != nullptr; }
std::unique_ptr<u8[]> BuildMemoryCardTex(u32& sizeOut, ETexelFormat& fmtOut, std::unique_ptr<u8[]>& paletteOut) const; [[nodiscard]] u8* Lock();
const aurora::gfx::TextureHandle& GetFontTexture(EFontType tp); 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; } static void SetCurrentFrameCount(u32 frameCount) { sCurrentFrameCount = frameCount; }
}; };
CFactoryFnReturn FTextureFactory(const metaforce::SObjectTag& tag, std::unique_ptr<u8[]>&& in, u32 len, CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
const metaforce::CVParamTransfer& vparms, CObjectReference* selfRef); CObjectReference* selfRef);
} // namespace metaforce } // 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 #pragma once
#include <cstdint> #include <cstdint>
#include <cstddef>
namespace GX { namespace GX {
enum AttrType { NONE, DIRECT, INDEX8, INDEX16 }; enum AttrType { NONE, DIRECT, INDEX8, INDEX16 };

View File

@ -36,7 +36,7 @@ void CSpaceWarpFilter::GenerateWarpRampTex() {
} }
} }
m_warpTex = aurora::gfx::new_static_texture_2d( 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"); {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::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_flipRect = true; // TODO?
m_tex = tex; m_tex = tex;
} }
@ -339,7 +339,7 @@ CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, const auror
} }
CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, TLockedToken<CTexture> tex) CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, TLockedToken<CTexture> tex)
: CTexturedQuadFilterAlpha(type, (tex ? tex->GetTexture() : aurora::gfx::TextureHandle{})) { : CTexturedQuadFilterAlpha(type, aurora::gfx::TextureHandle{}) {
m_tex = tex; m_tex = tex;
} }

View File

@ -19,7 +19,7 @@ void CXRayBlurFilter::Shutdown() {
// s_Pipeline.reset(); // 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) { // CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
// struct Vert { // struct Vert {
// zeus::CVector2f m_pos; // 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; bool zTest = xac_drawFlags == EGuiModelDrawFlags::Shadeless || xac_drawFlags == EGuiModelDrawFlags::Opaque;
if (noBlur) { if (noBlur) {
aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(), // aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, 0); // aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, 0);
// quad.drawVerts(useColor, verts); // quad.drawVerts(useColor, verts);
} else if ((x14c_deResFactor == 0.f && alpha == 1.f) || tex.GetNumMips() == 1) { } 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::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, 0); // aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, 0);
} else { } else {
const float tmp = (1.f - x14c_deResFactor) * alpha; const float tmp = (1.f - x14c_deResFactor) * alpha;
const float tmp3 = 1.f - tmp * tmp * tmp; const float tmp3 = 1.f - tmp * tmp * tmp;
const float mip = tmp3 * static_cast<float>(tex.GetNumMips() - 1); const float mip = tmp3 * static_cast<float>(tex.GetNumberOfMipMaps() - 1);
aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(), // aurora::gfx::queue_textured_quad_verts(aurora::gfx::CameraFilterType(filter), tex.GetTexture(),
aurora::gfx::ZComp::LEqual, zTest, useColor, xe0_coords, realUseUvs, mip); // 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 char16_t* str, int len) const;
const CGlyph* GetGlyph(char16_t chr) const { return InternalGetGlyph(chr); } 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; 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; bool IsFinishedLoading() const;
}; };

View File

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

View File

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

View File

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

View File

@ -350,8 +350,6 @@ void CSaveGameScreen::SetUIText() {
x68_textpane_choice3->TextSupport().SetText(opt3Str); x68_textpane_choice3->TextSupport().SetText(opt3Str);
m_touchBar->SetUIOpts(opt0Str, opt1Str, opt2Str);
x5c_textpane_choice0->SetIsSelectable(opt0 != -1); x5c_textpane_choice0->SetIsSelectable(opt0 != -1);
x60_textpane_choice1->SetIsSelectable(opt1 != -1); x60_textpane_choice1->SetIsSelectable(opt1 != -1);
x64_textpane_choice2->SetIsSelectable(opt2 != -1); x64_textpane_choice2->SetIsSelectable(opt2 != -1);
@ -597,13 +595,6 @@ void CSaveGameScreen::DoSelectionChange([[maybe_unused]] CGuiTableGroup* caller,
void CSaveGameScreen::ProcessUserInput(const CFinalInput& input) { void CSaveGameScreen::ProcessUserInput(const CFinalInput& input) {
if (x50_loadedFrame != nullptr) { if (x50_loadedFrame != nullptr) {
x50_loadedFrame->ProcessUserInput(input); 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) 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"); x14_txtrSaveBanner = g_SimplePool->GetObj("TXTR_SaveBanner");
x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0"); x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0");
x2c_txtrSaveIcon1 = g_SimplePool->GetObj("TXTR_SaveIcon1"); x2c_txtrSaveIcon1 = g_SimplePool->GetObj("TXTR_SaveIcon1");

View File

@ -7,7 +7,6 @@
#include "Runtime/CToken.hpp" #include "Runtime/CToken.hpp"
#include "Runtime/GuiSys/CGuiFrame.hpp" #include "Runtime/GuiSys/CGuiFrame.hpp"
#include "Runtime/MP1/CMemoryCardDriver.hpp" #include "Runtime/MP1/CMemoryCardDriver.hpp"
#include "Runtime/MP1/CSaveGameScreenTouchBar.hpp"
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
namespace metaforce { namespace metaforce {
@ -85,8 +84,6 @@ private:
bool x92_savingDisabled = false; bool x92_savingDisabled = false;
bool x93_inGame; bool x93_inGame;
std::unique_ptr<CSaveGameScreenTouchBar> m_touchBar;
void ContinueWithoutSaving(); void ContinueWithoutSaving();
public: 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()) { 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('PART'), FFactoryFunc(FParticleFactory));
fmgr->AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame)); fmgr->AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame));
fmgr->AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory)); 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::SetModelMatrix(zeus::CTransform());
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear); CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
CGraphics::SetTevOp(0, CGraphics::sTevPass805a5ebc); CGraphics::SetTevOp(0, CGraphics::sTevPass805a5ebc);
CGraphics::SetTevOp(1, CGraphics::sTevPass805a564c); CGraphics::SetTevOp(1, CGraphics::skPassThru);
CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false); CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false);
CGraphics::StreamColor(zeus::CColor(f1, f1)); CGraphics::StreamColor(zeus::CColor(f1, f1));
CGraphics::StreamBegin(0xa0); CGraphics::StreamBegin(0xa0);

View File

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

View File

@ -60,7 +60,7 @@ CPlasmaProjectile::CPlasmaProjectile(const TToken<CWeaponDescription>& wDesc, st
x51c_pulseGen->SetParticleEmission(false); x51c_pulseGen->SetParticleEmission(false);
// CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { // 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; // return true;
// } BooTrace); // } BooTrace);
} }

View File

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

View File

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

View File

@ -135,7 +135,7 @@ void CFluidPlaneManager::SetupRippleMap() {
curX += (1.f / 63.f); 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}, {reinterpret_cast<const uint8_t*>(RippleValues.data()), 64 * 64},
"Ripple Map"); "Ripple Map");
} }

View File

@ -3,7 +3,7 @@
namespace metaforce { namespace metaforce {
CProjectedShadow::CProjectedShadow(u32 w, u32 h, bool persistent) 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 {}; } zeus::CAABox CProjectedShadow::CalculateRenderBounds() { return {}; }

View File

@ -27,9 +27,11 @@ add_library(aurora STATIC
lib/gfx/movie_player/shader.cpp lib/gfx/movie_player/shader.cpp
lib/gfx/textured_quad/shader.cpp lib/gfx/textured_quad/shader.cpp
lib/gfx/colored_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_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 ../imgui ../extern/imgui)
target_include_directories(aurora PRIVATE target_include_directories(aurora PRIVATE
../extern/dawn/src ../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 zstring_view_literals
} // namespace literals } // namespace literals
} // namespace aurora } // 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" #include "common.hpp"
// TODO make this shared?
#include "../../../Runtime/Graphics/GX.hpp"
#include <cstdint> #include <cstdint>
#include <utility> #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 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 { struct CFogState {
zeus::CColor m_color; zeus::CColor m_color;
float m_A = 0.f; float m_A = 0.f;
@ -86,6 +133,41 @@ struct CFogState {
float m_C = 0.f; float m_C = 0.f;
ERglFogMode m_mode; 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 metaforce
namespace aurora::gfx { namespace aurora::gfx {
@ -138,6 +220,16 @@ enum class ZComp : uint8_t {
[[nodiscard]] bool get_dxt_compression_supported() noexcept; [[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 // GX state
void set_cull_mode(metaforce::ERglCullMode mode) noexcept; void set_cull_mode(metaforce::ERglCullMode mode) noexcept;
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst, 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, void queue_colored_quad(CameraFilterType filter_type, ZComp z_comparison, bool z_test, const zeus::CColor& color,
const zeus::CRectangle& rect, float z) noexcept; const zeus::CRectangle& rect, float z) noexcept;
void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v, 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; 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; zstring_view label) noexcept;
TextureHandle new_render_texture(uint32_t width, uint32_t height, uint32_t color_bind_count, uint32_t depth_bind_count, TextureHandle new_render_texture(uint32_t width, uint32_t height, uint32_t color_bind_count, uint32_t depth_bind_count,
zstring_view label) noexcept; 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, 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,
auto data = movie_player::make_draw_data(g_state.moviePlayer, tex_y, tex_u, tex_v, color, h_pad, v_pad); 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}); push_draw_command({.type = ShaderType::MoviePlayer, .moviePlayer = data});
} }
template <> template <>

View File

@ -21,18 +21,38 @@ static inline XXH64_hash_t xxh3_hash(const T& input, XXH64_hash_t seed = 0) {
class ByteBuffer { class ByteBuffer {
public: public:
ByteBuffer() = default; ByteBuffer() noexcept = default;
explicit ByteBuffer(size_t capacity) : m_data(static_cast<uint8_t*>(calloc(1, capacity))), m_capacity(capacity) {} explicit ByteBuffer(size_t size) noexcept
: m_data(static_cast<uint8_t*>(calloc(1, size))), m_length(size), m_capacity(size) {}
~ByteBuffer() { ~ByteBuffer() noexcept {
if (m_data != nullptr) { if (m_data != nullptr) {
free(m_data); 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; } [[nodiscard]] uint8_t* data() noexcept { return m_data; }
const uint8_t* data() const { return m_data; } [[nodiscard]] const uint8_t* data() const noexcept { return m_data; }
size_t size() const { return m_length; } [[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) { void append(const void* data, size_t size) {
resize(m_length + size); resize(m_length + size);
@ -136,9 +156,17 @@ struct TextureRef {
wgpu::TextureView view; wgpu::TextureView view;
wgpu::Extent3D size; wgpu::Extent3D size;
wgpu::TextureFormat format; wgpu::TextureFormat format;
uint32_t mipCount;
metaforce::ETexelFormat gameFormat;
TextureRef(wgpu::Texture&& texture, wgpu::TextureView&& view, wgpu::Extent3D size, wgpu::TextureFormat format) 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) {} 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; 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, 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{}); auto pipeline = pipeline_ref(PipelineConfig{});
const std::array verts{ const std::array verts{
Vert{{-h_pad, v_pad, 0.f}, {0.0, 0.0}}, Vert{{v1.x(), v1.z(), v1.y()}, {0.0, 0.0}},
Vert{{-h_pad, -v_pad, 0.f}, {0.0, 1.0}}, Vert{{v2.x(), v2.z(), v2.y()}, {0.0, 1.0}},
Vert{{h_pad, v_pad, 0.f}, {1.0, 0.0}}, Vert{{v3.x(), v3.z(), v3.y()}, {1.0, 0.0}},
Vert{{h_pad, -v_pad, 0.f}, {1.0, 1.0}}, Vert{{v4.x(), v4.z(), v4.y()}, {1.0, 1.0}},
}; };
const auto vertRange = push_verts(ArrayRef{verts}); const auto vertRange = push_verts(ArrayRef{verts});
const auto uniform = Uniform{ const auto uniform = Uniform{
.xf = Mat4x4_Identity, .xf = Mat4x4_Identity,
.color = color, .color = zeus::skWhite,
}; };
const auto uniformRange = push_uniform(uniform); const auto uniformRange = push_uniform(uniform);

View File

@ -36,6 +36,7 @@ struct alignas(4) Uniform {
State construct_state(); State construct_state();
wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] PipelineConfig config); 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, 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); void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass);
} // namespace aurora::gfx::movie_player } // 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 "common.hpp"
#include "../gpu.hpp" #include "../gpu.hpp"
#include "texture_convert.hpp"
#include <logvisor/logvisor.hpp> #include <logvisor/logvisor.hpp>
#include <magic_enum.hpp> #include <magic_enum.hpp>
@ -11,24 +12,6 @@ static logvisor::Module Log("aurora::gfx");
using gpu::g_device; using gpu::g_device;
using gpu::g_queue; 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 { struct TextureFormatInfo {
uint8_t blockWidth; uint8_t blockWidth;
uint8_t blockHeight; uint8_t blockHeight;
@ -55,10 +38,19 @@ static wgpu::Extent3D physical_size(wgpu::Extent3D size, TextureFormatInfo info)
return {width, height, size.depthOrArrayLayers}; 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 { ArrayRef<uint8_t> data, zstring_view label) noexcept {
auto handle = new_dynamic_texture_2d(width, height, mips, format, label); auto handle = new_dynamic_texture_2d(width, height, mips, format, label);
const TextureRef& ref = *handle.ref; 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; uint32_t offset = 0;
for (uint32_t mip = 0; mip < mips; ++mip) { for (uint32_t mip = 0; mip < mips; ++mip) {
const auto mipSize = wgpu::Extent3D{ 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; 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 { zstring_view label) noexcept {
const auto wgpuFormat = to_wgpu(format); const auto wgpuFormat = to_wgpu(format);
const auto size = wgpu::Extent3D{ 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 texture = g_device.CreateTexture(&textureDescriptor);
auto textureView = texture.CreateView(&textureViewDescriptor); 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, 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 // TODO accept mip/layer parameters
void write_texture(const TextureHandle& handle, ArrayRef<uint8_t> data) noexcept { void write_texture(const TextureHandle& handle, ArrayRef<uint8_t> data) noexcept {
const TextureRef& ref = *handle.ref; 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{ const auto dstView = wgpu::ImageCopyTexture{
.texture = ref.texture, .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(); ImGuiIO& io = ImGui::GetIO();
io.Fonts->Clear(); 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>( auto stream = std::make_unique<metaforce::CMemoryInStream>(
static_cast<const u8*>(NOTO_MONO_FONT), NOTO_MONO_FONT_SZ, metaforce::CMemoryInStream::EOwnerShip::NotOwned); static_cast<const u8*>(NOTO_MONO_FONT), NOTO_MONO_FONT_SZ, metaforce::CMemoryInStream::EOwnerShip::NotOwned);
metaforce::CZipInputStream zipInputStream{std::move(stream)}; 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{}; ImFontConfig fontConfig{};