2024-03-24 02:01:28 -06:00
|
|
|
#include "Engine.h"
|
|
|
|
#include "ui/ImguiUI.h"
|
2024-05-20 22:29:07 -06:00
|
|
|
#include "StringHelper.h"
|
2024-03-24 02:01:28 -06:00
|
|
|
#include "libultraship/src/Context.h"
|
2024-04-06 04:25:11 -06:00
|
|
|
#include "resource/type/ResourceType.h"
|
|
|
|
#include "resource/importers/AnimFactory.h"
|
2024-04-07 00:41:12 +01:00
|
|
|
#include "resource/importers/ColPolyFactory.h"
|
2024-04-06 14:25:40 -06:00
|
|
|
#include "resource/importers/EnvSettingsFactory.h"
|
2024-04-07 02:01:49 +01:00
|
|
|
#include "resource/importers/GenericArrayFactory.h"
|
2024-04-06 14:25:40 -06:00
|
|
|
#include "resource/importers/HitboxFactory.h"
|
2024-04-06 04:25:11 -06:00
|
|
|
#include "resource/importers/LimbFactory.h"
|
|
|
|
#include "resource/importers/MessageFactory.h"
|
|
|
|
#include "resource/importers/MessageLookupFactory.h"
|
2024-04-06 14:25:40 -06:00
|
|
|
#include "resource/importers/ObjectInitFactory.h"
|
|
|
|
#include "resource/importers/ScriptCommandFactory.h"
|
|
|
|
#include "resource/importers/ScriptFactory.h"
|
2024-04-06 04:25:11 -06:00
|
|
|
#include "resource/importers/SkeletonFactory.h"
|
2024-04-07 00:41:12 +01:00
|
|
|
#include "resource/importers/Vec3fFactory.h"
|
|
|
|
#include "resource/importers/Vec3sFactory.h"
|
2024-05-20 22:29:07 -06:00
|
|
|
#include <Fast3D/Fast3dWindow.h>
|
|
|
|
#include <DisplayListFactory.h>
|
|
|
|
#include <TextureFactory.h>
|
|
|
|
#include <MatrixFactory.h>
|
|
|
|
#include <ArrayFactory.h>
|
|
|
|
#include <BlobFactory.h>
|
|
|
|
#include <VertexFactory.h>
|
2024-03-24 02:01:28 -06:00
|
|
|
|
|
|
|
#include <Fast3D/gfx_pc.h>
|
|
|
|
#include <Fast3D/gfx_rendering_api.h>
|
2024-04-02 09:39:25 -06:00
|
|
|
#include <SDL2/SDL.h>
|
2024-03-24 02:01:28 -06:00
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
extern "C" {
|
2024-05-20 22:29:07 -06:00
|
|
|
extern uint16_t gFPS;
|
2024-03-24 02:01:28 -06:00
|
|
|
float gInterpolationStep = 0.0f;
|
2024-04-01 23:13:52 -06:00
|
|
|
#include <sf64thread.h>
|
|
|
|
#include <macros.h>
|
2024-03-24 02:01:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
GameEngine* GameEngine::Instance;
|
|
|
|
|
|
|
|
GameEngine::GameEngine() {
|
|
|
|
std::vector<std::string> OTRFiles;
|
2024-05-20 22:29:07 -06:00
|
|
|
if (const std::string cube_path = Ship::Context::GetPathRelativeToAppDirectory("starship.otr"); std::filesystem::exists(cube_path)) {
|
2024-04-06 04:25:11 -06:00
|
|
|
OTRFiles.push_back(cube_path);
|
|
|
|
}
|
2024-05-20 22:29:07 -06:00
|
|
|
if (const std::string sm64_otr_path = Ship::Context::GetPathRelativeToAppBundle("sm64.otr"); std::filesystem::exists(sm64_otr_path)) {
|
2024-03-24 02:01:28 -06:00
|
|
|
OTRFiles.push_back(sm64_otr_path);
|
|
|
|
}
|
2024-05-20 22:29:07 -06:00
|
|
|
if (const std::string patches_path = Ship::Context::GetPathRelativeToAppDirectory("mods"); !patches_path.empty() && std::filesystem::exists(patches_path)) {
|
2024-03-24 02:01:28 -06:00
|
|
|
if (std::filesystem::is_directory(patches_path)) {
|
|
|
|
for (const auto&p: std::filesystem::recursive_directory_iterator(patches_path)) {
|
|
|
|
if (StringHelper::IEquals(p.path().extension().string(), ".otr")) {
|
|
|
|
OTRFiles.push_back(p.path().generic_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-04-06 04:25:11 -06:00
|
|
|
|
2024-05-20 22:29:07 -06:00
|
|
|
this->context = Ship::Context::CreateInstance("Starship", "ship", "starship.cfg.json", OTRFiles, {}, 3);
|
2024-04-06 04:25:11 -06:00
|
|
|
|
|
|
|
auto loader = context->GetResourceManager()->GetResourceLoader();
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryAnimV0>(), RESOURCE_FORMAT_BINARY, "Animation", static_cast<uint32_t>(SF64::ResourceType::AnimData), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinarySkeletonV0>(), RESOURCE_FORMAT_BINARY, "Skeleton", static_cast<uint32_t>(SF64::ResourceType::Skeleton), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryLimbV0>(), RESOURCE_FORMAT_BINARY, "Limb", static_cast<uint32_t>(SF64::ResourceType::Limb), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryMessageV0>(), RESOURCE_FORMAT_BINARY, "Message", static_cast<uint32_t>(SF64::ResourceType::Message), 0);
|
2024-04-06 14:25:40 -06:00
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryMessageLookupV0>(), RESOURCE_FORMAT_BINARY, "MessageTable", static_cast<uint32_t>(SF64::ResourceType::MessageTable), 0);
|
2024-05-20 22:29:07 -06:00
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryEnvSettingsV0>(), RESOURCE_FORMAT_BINARY, "EnvSettings", static_cast<uint32_t>(SF64::ResourceType::Environment), 0);
|
2024-04-06 14:25:40 -06:00
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryObjectInitV0>(), RESOURCE_FORMAT_BINARY, "ObjectInit", static_cast<uint32_t>(SF64::ResourceType::ObjectInit), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryHitboxV0>(), RESOURCE_FORMAT_BINARY, "Hitbox", static_cast<uint32_t>(SF64::ResourceType::Hitbox), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryScriptV0>(), RESOURCE_FORMAT_BINARY, "Script", static_cast<uint32_t>(SF64::ResourceType::Script), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryScriptCMDV0>(), RESOURCE_FORMAT_BINARY, "ScriptCMD", static_cast<uint32_t>(SF64::ResourceType::ScriptCmd), 0);
|
2024-04-07 00:41:12 +01:00
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryColPolyV0>(), RESOURCE_FORMAT_BINARY, "ColPoly", static_cast<uint32_t>(SF64::ResourceType::ColPoly), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryVec3fV0>(), RESOURCE_FORMAT_BINARY, "Vec3f", static_cast<uint32_t>(SF64::ResourceType::Vec3f), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryVec3sV0>(), RESOURCE_FORMAT_BINARY, "Vec3s", static_cast<uint32_t>(SF64::ResourceType::Vec3s), 0);
|
2024-04-07 02:01:49 +01:00
|
|
|
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryGenericArrayV0>(), RESOURCE_FORMAT_BINARY, "GenericArray", static_cast<uint32_t>(SF64::ResourceType::GenericArray), 0);
|
2024-05-20 22:29:07 -06:00
|
|
|
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryTextureV0>(), RESOURCE_FORMAT_BINARY, "Texture", static_cast<uint32_t>(LUS::ResourceType::Texture), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryTextureV1>(), RESOURCE_FORMAT_BINARY, "Texture", static_cast<uint32_t>(LUS::ResourceType::Texture), 1);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryVertexV0>(), RESOURCE_FORMAT_BINARY, "Vertex", static_cast<uint32_t>(LUS::ResourceType::Vertex), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryDisplayListV0>(), RESOURCE_FORMAT_BINARY, "DisplayList", static_cast<uint32_t>(LUS::ResourceType::DisplayList), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryMatrixV0>(), RESOURCE_FORMAT_BINARY, "Matrix", static_cast<uint32_t>(LUS::ResourceType::Matrix), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryArrayV0>(), RESOURCE_FORMAT_BINARY, "Array", static_cast<uint32_t>(LUS::ResourceType::Array), 0);
|
|
|
|
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryBlobV0>(), RESOURCE_FORMAT_BINARY, "Blob", static_cast<uint32_t>(LUS::ResourceType::Blob), 0);
|
2024-03-24 02:01:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void GameEngine::Create(){
|
|
|
|
const auto instance = Instance = new GameEngine();
|
|
|
|
GameUI::SetupGuiElements();
|
2024-04-10 17:01:29 -06:00
|
|
|
#if defined(__SWITCH__) || defined(__WIIU__)
|
|
|
|
CVarRegisterInteger("gControlNav", 1); // always enable controller nav on switch/wii u
|
|
|
|
#endif
|
2024-03-24 02:01:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void GameEngine::Destroy(){
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShouldClearTextureCacheAtEndOfFrame = false;
|
|
|
|
|
|
|
|
void GameEngine::StartFrame() const{
|
2024-05-20 22:29:07 -06:00
|
|
|
using Ship::KbScancode;
|
2024-03-24 02:01:28 -06:00
|
|
|
const int32_t dwScancode = this->context->GetWindow()->GetLastScancode();
|
|
|
|
this->context->GetWindow()->SetLastScancode(-1);
|
|
|
|
|
|
|
|
switch (dwScancode) {
|
|
|
|
case KbScancode::LUS_KB_TAB: {
|
|
|
|
// Toggle HD Assets
|
|
|
|
CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0));
|
|
|
|
ShouldClearTextureCacheAtEndOfFrame = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
this->context->GetWindow()->StartFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameEngine::RunCommands(Gfx* Commands) {
|
|
|
|
gfx_run(Commands, {});
|
|
|
|
gfx_end_frame();
|
|
|
|
|
|
|
|
if (ShouldClearTextureCacheAtEndOfFrame) {
|
|
|
|
gfx_texture_cache_clear();
|
|
|
|
ShouldClearTextureCacheAtEndOfFrame = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameEngine::ProcessGfxCommands(Gfx* commands) {
|
2024-05-20 22:29:07 -06:00
|
|
|
auto wnd = std::dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow());
|
|
|
|
|
|
|
|
if (wnd == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gFPS = 30;
|
|
|
|
wnd->SetRendererUCode(UcodeHandlers::ucode_f3dex);
|
2024-05-28 02:07:15 -03:00
|
|
|
wnd->SetTargetFps(60 / gVIsPerFrame);
|
2024-05-20 22:29:07 -06:00
|
|
|
wnd->SetMaximumFrameLatency(1);
|
|
|
|
|
2024-03-24 02:01:28 -06:00
|
|
|
RunCommands(commands);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" uint32_t GameEngine_GetSampleRate() {
|
2024-05-20 22:29:07 -06:00
|
|
|
auto player = Ship::Context::GetInstance()->GetAudio()->GetAudioPlayer();
|
2024-03-24 02:01:28 -06:00
|
|
|
if (player == nullptr) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!player->IsInitialized()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return player->GetSampleRate();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" uint32_t GameEngine_GetSamplesPerFrame(){
|
|
|
|
return SAMPLES_PER_FRAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
// End
|
|
|
|
|
|
|
|
extern "C" float GameEngine_GetAspectRatio() {
|
|
|
|
return gfx_current_dimensions.aspect_ratio;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" uint32_t GameEngine_GetGameVersion() {
|
|
|
|
return 0x00000001;
|
|
|
|
}
|
|
|
|
|
2024-04-07 18:01:42 -06:00
|
|
|
static const char* sOtrSignature = "__OTR__";
|
|
|
|
|
|
|
|
extern "C" uint8_t GameEngine_OTRSigCheck(const char* data) {
|
|
|
|
if(data == nullptr) {
|
|
|
|
return 0;
|
|
|
|
}
|
2024-03-24 02:01:28 -06:00
|
|
|
return strncmp(data, sOtrSignature, strlen(sOtrSignature)) == 0;
|
2024-04-01 23:13:52 -06:00
|
|
|
}
|
|
|
|
|
2024-04-03 09:57:24 -06:00
|
|
|
extern "C" float __cosf(float angle) {
|
2024-04-09 12:49:20 -06:00
|
|
|
return cosf(angle);
|
2024-04-03 09:57:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" float __sinf(float angle) {
|
2024-04-09 12:49:20 -06:00
|
|
|
return sinf(angle);
|
2024-04-03 09:57:24 -06:00
|
|
|
}
|
|
|
|
|
2024-04-01 23:13:52 -06:00
|
|
|
extern "C" float SIN_DEG(float angle) {
|
2024-04-03 09:58:56 -06:00
|
|
|
return __sinf(M_DTOR * angle);
|
2024-04-01 23:13:52 -06:00
|
|
|
}
|
|
|
|
extern "C" float COS_DEG(float angle) {
|
2024-04-03 09:58:56 -06:00
|
|
|
return __cosf(M_DTOR * angle);
|
2024-04-01 23:13:52 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
struct TimedEntry {
|
|
|
|
uint64_t duration;
|
|
|
|
TimerAction action;
|
|
|
|
int32_t* address;
|
|
|
|
int32_t value;
|
|
|
|
bool active;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<TimedEntry> gTimerTasks;
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t Timer_GetCurrentMillis() {
|
|
|
|
return SDL_GetTicks();
|
|
|
|
}
|
|
|
|
|
2024-04-09 12:49:20 -06:00
|
|
|
extern "C" s32 Timer_CreateTask(u64 time, TimerAction action, s32* address, s32 value) {
|
2024-04-01 23:13:52 -06:00
|
|
|
const auto millis = Timer_GetCurrentMillis();
|
|
|
|
TimedEntry entry = {
|
|
|
|
.duration = millis + CYCLES_TO_MSEC_PC(time),
|
|
|
|
.action = action,
|
|
|
|
.address = address,
|
|
|
|
.value = value,
|
|
|
|
.active = true,
|
|
|
|
};
|
|
|
|
|
|
|
|
gTimerTasks.push_back(entry);
|
|
|
|
|
|
|
|
return gTimerTasks.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void Timer_Increment(int32_t* address, int32_t value) {
|
|
|
|
*address += value;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void Timer_SetValue(int32_t* address, int32_t value) {
|
|
|
|
*address = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Timer_CompleteTask(TimedEntry& task) {
|
|
|
|
if (task.action != nullptr) {
|
|
|
|
task.action(task.address, task.value);
|
|
|
|
}
|
|
|
|
task.active = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void Timer_Update() {
|
|
|
|
|
|
|
|
if(gTimerTasks.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto millis = Timer_GetCurrentMillis();
|
|
|
|
|
|
|
|
for (auto& task : gTimerTasks) {
|
|
|
|
if (task.active && millis >= task.duration) {
|
|
|
|
Timer_CompleteTask(task);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-05-27 15:27:19 -06:00
|
|
|
|
|
|
|
// Gets the width of the main ImGui window
|
|
|
|
extern "C" uint32_t OTRGetCurrentWidth() {
|
|
|
|
return GameEngine::Instance->context->GetWindow()->GetWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the height of the main ImGui window
|
|
|
|
extern "C" uint32_t OTRGetCurrentHeight() {
|
|
|
|
return GameEngine::Instance->context->GetWindow()->GetHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" float OTRGetAspectRatio() {
|
|
|
|
return gfx_current_dimensions.aspect_ratio;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" float OTRGetDimensionFromLeftEdge(float v) {
|
|
|
|
return (gfx_native_dimensions.width / 2 - gfx_native_dimensions.height / 2 * OTRGetAspectRatio() + (v));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" float OTRGetDimensionFromRightEdge(float v) {
|
|
|
|
return (gfx_native_dimensions.width / 2 + gfx_native_dimensions.height / 2 * OTRGetAspectRatio() -
|
|
|
|
(gfx_native_dimensions.width - v));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the width of the current render target area
|
|
|
|
extern "C" uint32_t OTRGetGameRenderWidth() {
|
|
|
|
return gfx_current_dimensions.width;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the height of the current render target area
|
|
|
|
extern "C" uint32_t OTRGetGameRenderHeight() {
|
|
|
|
return gfx_current_dimensions.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int16_t OTRGetRectDimensionFromLeftEdge(float v) {
|
|
|
|
return ((int)floorf(OTRGetDimensionFromLeftEdge(v)));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int16_t OTRGetRectDimensionFromRightEdge(float v) {
|
|
|
|
return ((int)ceilf(OTRGetDimensionFromRightEdge(v)));
|
|
|
|
}
|