mirror of https://github.com/AxioDL/metaforce.git
Update submodules; changes for emscripten support
This commit is contained in:
parent
324d89693c
commit
e2fbc0663f
|
@ -73,6 +73,9 @@ if (APPLE AND NOT TVOS AND CMAKE_SYSTEM_NAME STREQUAL tvOS)
|
|||
set(TVOS ON)
|
||||
set(IOS OFF)
|
||||
endif ()
|
||||
if (EMSCRIPTEN)
|
||||
set(CMAKE_EXECUTABLE_SUFFIX .html)
|
||||
endif ()
|
||||
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" ATHENA_ARCH)
|
||||
string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}" ATHENA_HOST_ARCH)
|
||||
|
|
|
@ -19,25 +19,50 @@ class CFileDvdRequest : public IDvdRequest {
|
|||
u32 m_len;
|
||||
ESeekOrigin m_whence;
|
||||
int m_offset;
|
||||
|
||||
#ifdef HAS_DVD_THREAD
|
||||
std::atomic_bool m_cancel = {false};
|
||||
std::atomic_bool m_complete = {false};
|
||||
#else
|
||||
bool m_cancel = false;
|
||||
bool m_complete = false;
|
||||
#endif
|
||||
std::function<void(u32)> m_callback;
|
||||
|
||||
public:
|
||||
~CFileDvdRequest() override { CFileDvdRequest::PostCancelRequest(); }
|
||||
|
||||
void WaitUntilComplete() override {
|
||||
#ifdef HAS_DVD_THREAD
|
||||
while (!m_complete.load() && !m_cancel.load()) {
|
||||
std::unique_lock lk{CDvdFile::m_WaitMutex};
|
||||
}
|
||||
#else
|
||||
if (!m_complete && !m_cancel) {
|
||||
CDvdFile::DoWork();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
bool IsComplete() override {
|
||||
#ifdef HAS_DVD_THREAD
|
||||
return m_complete.load();
|
||||
#else
|
||||
if (!m_complete) {
|
||||
CDvdFile::DoWork();
|
||||
}
|
||||
return m_complete;
|
||||
#endif
|
||||
}
|
||||
bool IsComplete() override { return m_complete.load(); }
|
||||
void PostCancelRequest() override {
|
||||
#ifdef HAS_DVD_THREAD
|
||||
if (m_complete.load() || m_cancel.load()) {
|
||||
return;
|
||||
}
|
||||
std::unique_lock waitlk{CDvdFile::m_WaitMutex};
|
||||
m_cancel.store(true);
|
||||
#else
|
||||
m_cancel = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] EMediaType GetMediaType() const override { return EMediaType::File; }
|
||||
|
@ -53,9 +78,15 @@ public:
|
|||
, m_callback(std::move(cb)) {}
|
||||
|
||||
void DoRequest() {
|
||||
#ifdef HAS_DVD_THREAD
|
||||
if (m_cancel.load()) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (m_cancel) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
u32 readLen = 0;
|
||||
if (m_whence == ESeekOrigin::Cur && m_offset == 0) {
|
||||
readLen = m_reader->read(m_buf, m_len);
|
||||
|
@ -84,15 +115,21 @@ public:
|
|||
if (m_callback) {
|
||||
m_callback(readLen);
|
||||
}
|
||||
#ifdef HAS_DVD_THREAD
|
||||
m_complete.store(true);
|
||||
#else
|
||||
m_complete = true;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef HAS_DVD_THREAD
|
||||
std::thread CDvdFile::m_WorkerThread;
|
||||
std::mutex CDvdFile::m_WorkerMutex;
|
||||
std::condition_variable CDvdFile::m_WorkerCV;
|
||||
std::mutex CDvdFile::m_WaitMutex;
|
||||
std::atomic_bool CDvdFile::m_WorkerRun = {false};
|
||||
#endif
|
||||
std::vector<std::shared_ptr<IDvdRequest>> CDvdFile::m_RequestQueue;
|
||||
std::string CDvdFile::m_rootDirectory;
|
||||
std::unique_ptr<u8[]> CDvdFile::m_dolBuf;
|
||||
|
@ -106,7 +143,17 @@ CDvdFile::CDvdFile(std::string_view path) : x18_path(path) {
|
|||
}
|
||||
}
|
||||
|
||||
// single-threaded hack
|
||||
void CDvdFile::DoWork() {
|
||||
for (std::shared_ptr<IDvdRequest>& req : m_RequestQueue) {
|
||||
auto& concreteReq = static_cast<CFileDvdRequest&>(*req);
|
||||
concreteReq.DoRequest();
|
||||
}
|
||||
m_RequestQueue.clear();
|
||||
}
|
||||
|
||||
void CDvdFile::WorkerProc() {
|
||||
#ifdef HAS_DVD_THREAD
|
||||
logvisor::RegisterThreadName("CDvdFile");
|
||||
OPTICK_THREAD("CDvdFile");
|
||||
|
||||
|
@ -130,15 +177,20 @@ void CDvdFile::WorkerProc() {
|
|||
}
|
||||
m_WorkerCV.wait(lk);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::shared_ptr<IDvdRequest> CDvdFile::AsyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int off,
|
||||
std::function<void(u32)>&& cb) {
|
||||
std::shared_ptr<IDvdRequest> ret = std::make_shared<CFileDvdRequest>(*this, buf, len, whence, off, std::move(cb));
|
||||
#ifdef HAS_DVD_THREAD
|
||||
std::unique_lock lk{m_WorkerMutex};
|
||||
#endif
|
||||
m_RequestQueue.emplace_back(ret);
|
||||
#ifdef HAS_DVD_THREAD
|
||||
lk.unlock();
|
||||
m_WorkerCV.notify_one();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -205,20 +257,25 @@ nod::Node* CDvdFile::ResolvePath(std::string_view path) {
|
|||
}
|
||||
|
||||
bool CDvdFile::Initialize(const std::string_view& path) {
|
||||
#ifdef HAS_DVD_THREAD
|
||||
if (m_WorkerRun.load()) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
m_DvdRoot = nod::OpenDiscFromImage(path);
|
||||
if (!m_DvdRoot) {
|
||||
return false;
|
||||
}
|
||||
m_dolBuf = m_DvdRoot->getDataPartition()->getDOLBuf();
|
||||
#ifdef HAS_DVD_THREAD
|
||||
m_WorkerRun.store(true);
|
||||
m_WorkerThread = std::thread(WorkerProc);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDvdFile::Shutdown() {
|
||||
#ifdef HAS_DVD_THREAD
|
||||
if (!m_WorkerRun.load()) {
|
||||
return;
|
||||
}
|
||||
|
@ -227,6 +284,7 @@ void CDvdFile::Shutdown() {
|
|||
if (m_WorkerThread.joinable()) {
|
||||
m_WorkerThread.join();
|
||||
}
|
||||
#endif
|
||||
m_RequestQueue.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
#include <nod/nod.hpp>
|
||||
#include <nod/DiscBase.hpp>
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
#define HAS_DVD_THREAD
|
||||
#endif
|
||||
|
||||
namespace metaforce {
|
||||
|
||||
enum class ESeekOrigin { Begin = 0, Cur = 1, End = 2 };
|
||||
|
@ -33,11 +37,13 @@ class CDvdFile {
|
|||
friend class CFileDvdRequest;
|
||||
static std::unique_ptr<nod::DiscBase> m_DvdRoot;
|
||||
// static std::unordered_map<std::string, std::string> m_caseInsensitiveMap;
|
||||
#ifdef HAS_DVD_THREAD
|
||||
static std::thread m_WorkerThread;
|
||||
static std::mutex m_WorkerMutex;
|
||||
static std::condition_variable m_WorkerCV;
|
||||
static std::mutex m_WaitMutex;
|
||||
static std::atomic_bool m_WorkerRun;
|
||||
#endif
|
||||
static std::vector<std::shared_ptr<IDvdRequest>> m_RequestQueue;
|
||||
static std::string m_rootDirectory;
|
||||
static std::unique_ptr<u8[]> m_dolBuf;
|
||||
|
@ -57,6 +63,7 @@ public:
|
|||
static void SetRootDirectory(const std::string_view& rootDir);
|
||||
static void Shutdown();
|
||||
static u8* GetDolBuf() { return m_dolBuf.get(); }
|
||||
static void DoWork();
|
||||
|
||||
CDvdFile(std::string_view path);
|
||||
operator bool() const { return m_reader.operator bool(); }
|
||||
|
|
|
@ -367,6 +367,9 @@ public:
|
|||
if (m_voiceEngine) {
|
||||
m_voiceEngine->pumpAndMixVoices();
|
||||
}
|
||||
#ifdef EMSCRIPTEN
|
||||
CDvdFile::DoWork();
|
||||
#endif
|
||||
CGraphics::TickRenderTimings();
|
||||
++logvisor::FrameIndex;
|
||||
}
|
||||
|
@ -433,12 +436,16 @@ static void SetupBasics() {
|
|||
}
|
||||
|
||||
static bool IsClientLoggingEnabled(int argc, char** argv) {
|
||||
#ifdef EMSCRIPTEN
|
||||
return true;
|
||||
#else
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (!strncmp(argv[i], "-l", 2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetupLogging() {}
|
||||
|
|
|
@ -154,7 +154,7 @@ if (NOT GEKKO AND NOT NX AND NOT IOS AND NOT TVOS)
|
|||
set(DISCORD_RPC_LIBRARY "discord-rpc")
|
||||
endif()
|
||||
set(RUNTIME_LIBRARIES amuse zeus nod NESEmulator libjpeg-turbo jbus kabufuda logvisor OptickCore
|
||||
imgui_support aurora::aurora SDL2::SDL2-static SDL2::SDL2main
|
||||
imgui_support aurora::aurora
|
||||
boo # TODO move audiodev
|
||||
${DISCORD_RPC_LIBRARY}
|
||||
${ZLIB_LIBRARIES}
|
||||
|
@ -278,3 +278,6 @@ if (WINDOWS_STORE)
|
|||
# This should match the Package.appxmanifest
|
||||
set_property(TARGET metaforce PROPERTY VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION "10.0.14393.0")
|
||||
endif ()
|
||||
if (EMSCRIPTEN)
|
||||
target_link_options(metaforce PRIVATE -sTOTAL_MEMORY=268435456 -sALLOW_MEMORY_GROWTH --preload-file "${CMAKE_SOURCE_DIR}/files@/")
|
||||
endif ()
|
||||
|
|
|
@ -700,11 +700,17 @@ void ImGuiConsole::ShowAboutWindow(bool preLaunch) {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef EMSCRIPTEN
|
||||
if (ImGuiButtonCenter("Load Game")) {
|
||||
m_gameDiscSelected = "game.iso";
|
||||
}
|
||||
#else
|
||||
if (!m_lastDiscPath.empty()) {
|
||||
if (ImGuiButtonCenter("Load Previous Game")) {
|
||||
m_gameDiscSelected = m_lastDiscPath;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ImGui::Dummy(padding);
|
||||
}
|
||||
if (m_errorString) {
|
||||
|
@ -828,7 +834,7 @@ void ImGuiConsole::ShowDebugOverlay() {
|
|||
}
|
||||
hasPrevious = true;
|
||||
|
||||
ImGuiStringViewText(fmt::format(FMT_STRING("FPS: {}\n"), metaforce::CGraphics::GetFPS()));
|
||||
ImGuiStringViewText(fmt::format(FMT_STRING("FPS: {:.1f}\n"), io.Framerate));
|
||||
}
|
||||
if (m_inGameTime && g_GameState != nullptr) {
|
||||
if (hasPrevious) {
|
||||
|
|
|
@ -5,20 +5,31 @@
|
|||
#include "Runtime/CBasics.hpp"
|
||||
#include "Runtime/CDvdRequest.hpp"
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
#define ENABLE_JBUS
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_JBUS
|
||||
#include <jbus/Endpoint.hpp>
|
||||
#include <jbus/Listener.hpp>
|
||||
#endif
|
||||
|
||||
namespace metaforce::MP1 {
|
||||
|
||||
#ifdef ENABLE_JBUS
|
||||
static jbus::Listener g_JbusListener;
|
||||
static std::unique_ptr<jbus::Endpoint> g_JbusEndpoint;
|
||||
#endif
|
||||
|
||||
void CGBASupport::Initialize() {
|
||||
#ifdef ENABLE_JBUS
|
||||
jbus::Initialize();
|
||||
g_JbusListener.start();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGBASupport::GlobalPoll() {
|
||||
#ifdef ENABLE_JBUS
|
||||
if (g_JbusEndpoint && !g_JbusEndpoint->connected())
|
||||
g_JbusEndpoint.reset();
|
||||
if (!g_JbusEndpoint) {
|
||||
|
@ -26,6 +37,7 @@ void CGBASupport::GlobalPoll() {
|
|||
if (g_JbusEndpoint)
|
||||
g_JbusEndpoint->setChan(3);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CGBASupport::CGBASupport() : CDvdFile("client_pad.bin") {
|
||||
|
@ -56,6 +68,7 @@ u8 CGBASupport::CalculateFusionJBusChecksum(const u8* data, size_t len) {
|
|||
}
|
||||
|
||||
bool CGBASupport::PollResponse() {
|
||||
#ifdef ENABLE_JBUS
|
||||
if (!g_JbusEndpoint)
|
||||
return false;
|
||||
|
||||
|
@ -127,10 +140,13 @@ bool CGBASupport::PollResponse() {
|
|||
if (x44_fusionLinked && (bytes[2] & 0x1) != 0)
|
||||
x45_fusionBeat = true;
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_JBUS
|
||||
static void JoyBootDone(jbus::ThreadLocalEndpoint& endpoint, jbus::EJoyReturn status) {}
|
||||
#endif
|
||||
|
||||
void CGBASupport::Update(float dt) {
|
||||
switch (x34_phase) {
|
||||
|
@ -144,6 +160,7 @@ void CGBASupport::Update(float dt) {
|
|||
[[fallthrough]];
|
||||
|
||||
case EPhase::PollProbe:
|
||||
#ifdef ENABLE_JBUS
|
||||
/* SIProbe poll normally occurs here with 4 second timeout */
|
||||
if (!g_JbusEndpoint) {
|
||||
x34_phase = EPhase::Failed;
|
||||
|
@ -151,17 +168,23 @@ void CGBASupport::Update(float dt) {
|
|||
}
|
||||
x40_siChan = g_JbusEndpoint->getChan();
|
||||
x34_phase = EPhase::StartJoyBusBoot;
|
||||
#endif
|
||||
[[fallthrough]];
|
||||
|
||||
case EPhase::StartJoyBusBoot:
|
||||
#ifdef ENABLE_JBUS
|
||||
x34_phase = EPhase::PollJoyBusBoot;
|
||||
if (!g_JbusEndpoint || g_JbusEndpoint->GBAJoyBootAsync(x40_siChan * 2, 2, x2c_buffer.get(), x28_fileSize,
|
||||
&x3c_status, JoyBootDone) != jbus::GBA_READY) {
|
||||
x34_phase = EPhase::Failed;
|
||||
}
|
||||
#else
|
||||
x34_phase = EPhase::Failed;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case EPhase::PollJoyBusBoot:
|
||||
#ifdef ENABLE_JBUS
|
||||
u8 percent;
|
||||
if (g_JbusEndpoint && g_JbusEndpoint->GBAGetProcessStatus(percent) == jbus::GBA_BUSY)
|
||||
break;
|
||||
|
@ -171,9 +194,13 @@ void CGBASupport::Update(float dt) {
|
|||
}
|
||||
x38_timeout = 4.f;
|
||||
x34_phase = EPhase::DataTransfer;
|
||||
#else
|
||||
x34_phase = EPhase::Failed;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case EPhase::DataTransfer:
|
||||
#ifdef ENABLE_JBUS
|
||||
if (PollResponse()) {
|
||||
x34_phase = EPhase::Complete;
|
||||
break;
|
||||
|
@ -181,6 +208,9 @@ void CGBASupport::Update(float dt) {
|
|||
x38_timeout = std::max(0.f, x38_timeout - dt);
|
||||
if (x38_timeout == 0.f)
|
||||
x34_phase = EPhase::Failed;
|
||||
#else
|
||||
x34_phase = EPhase::Failed;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
option(BUILD_ATHENA "Build Athena libraries from source" ON)
|
||||
if (WIN32 OR APPLE)
|
||||
if (CMAKE_HOST_SYSTEM_NAME STREQUAL Windows OR CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin)
|
||||
# Default to binary atdna on Windows & macOS
|
||||
option(BUILD_ATDNA "Build atdna utility from source (requires LLVM)" OFF)
|
||||
else ()
|
||||
|
@ -8,7 +8,7 @@ endif ()
|
|||
|
||||
if (NOT BUILD_ATDNA)
|
||||
set(ATHENA_BASE_URL "https://github.com/libAthena/athena/releases/download/latest")
|
||||
if (WIN32)
|
||||
if (CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)
|
||||
set(ATHENA_EXT 7z)
|
||||
else ()
|
||||
set(ATHENA_EXT tar.gz)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit c6046d91507d2a9dca46e29564acc0421322f7e9
|
||||
Subproject commit fa346ace4774e4ac66644be6d11908a80f0151b6
|
|
@ -1 +1 @@
|
|||
Subproject commit 04590f30cd90814d70fa7d1fe4a5f1e814b177c2
|
||||
Subproject commit 893cabe55a31a6f59c77854d503d891025204acb
|
|
@ -1 +1 @@
|
|||
Subproject commit 6e4030212c1a2a21a79a6d69660b6e7a52cf2885
|
||||
Subproject commit 39eb95a82440e1e614533b702e1cda814e01f69c
|
|
@ -1 +1 @@
|
|||
Subproject commit 32090b4d4ab70dbfa07f1f2994964f983ab43a69
|
||||
Subproject commit 4f3fbc0d0df2ee90a760b2d2e2bb8e2126bd92cb
|
|
@ -1 +1 @@
|
|||
Subproject commit ac7d83009dae97a28ba779d00188e3d76e9b9821
|
||||
Subproject commit e9ec10a3823a3c734e70c99b4aa50ae2a7e7e81f
|
|
@ -4,7 +4,7 @@ add_library(imgui_support
|
|||
NotoMono.cpp
|
||||
MetaforceIcon.cpp
|
||||
)
|
||||
target_link_libraries(imgui_support PUBLIC aurora::aurora imgui)
|
||||
target_link_libraries(imgui_support PUBLIC aurora::aurora imgui ${ZLIB_LIBRARIES})
|
||||
target_include_directories(imgui_support PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(imgui_support PRIVATE ${CMAKE_SOURCE_DIR})
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "ImGuiEngine.hpp"
|
||||
|
||||
#include <aurora/imgui.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "Runtime/Streams/CMemoryInStream.hpp"
|
||||
#include "Runtime/Streams/CZipInputStream.hpp"
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#define METAFORCE_DLPACKAGE "metaforce-@METAFORCE_WC_DESCRIBE@-@PLATFORM_NAME@-x86_64-@METAFORCE_VECTOR_ISA@"
|
||||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||
#define METAFORCE_DLPACKAGE "metaforce-@METAFORCE_WC_DESCRIBE@-@PLATFORM_NAME@-arm64"
|
||||
#elif defined(EMSCRIPTEN)
|
||||
#define METAFORCE_DLPACKAGE "metaforce-@METAFORCE_WC_DESCRIBE@-@PLATFORM_NAME@-wasm"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue