mirror of https://github.com/AxioDL/metaforce.git
Begin transitioning to new CTexture; start Stream API
This commit is contained in:
parent
00fd243f62
commit
740114af9e
|
@ -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
|
|
|
@ -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
|
|
|
@ -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>(); }
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
|
|
@ -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,25 +294,28 @@ 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);
|
||||||
|
@ -555,8 +560,7 @@ 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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,28 +192,27 @@ 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)
|
||||||
|
@ -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) */
|
||||||
|
|
|
@ -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}; }
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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>(); }
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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>(); }
|
|
||||||
|
|
||||||
}
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {}; }
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 <>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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{};
|
||||||
|
|
Loading…
Reference in New Issue