Update submodules; changes for emscripten support

This commit is contained in:
Luke Street 2022-08-03 18:19:11 -04:00
parent 324d89693c
commit e2fbc0663f
16 changed files with 128 additions and 11 deletions

View File

@ -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)

View File

@ -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();
}

View File

@ -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(); }

View File

@ -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() {}

View File

@ -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 ()

View File

@ -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) {

View File

@ -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:

View File

@ -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)

2
extern/athena vendored

@ -1 +1 @@
Subproject commit c6046d91507d2a9dca46e29564acc0421322f7e9
Subproject commit fa346ace4774e4ac66644be6d11908a80f0151b6

2
extern/aurora vendored

@ -1 +1 @@
Subproject commit 04590f30cd90814d70fa7d1fe4a5f1e814b177c2
Subproject commit 893cabe55a31a6f59c77854d503d891025204acb

2
extern/boo vendored

@ -1 +1 @@
Subproject commit 6e4030212c1a2a21a79a6d69660b6e7a52cf2885
Subproject commit 39eb95a82440e1e614533b702e1cda814e01f69c

2
extern/kabufuda vendored

@ -1 +1 @@
Subproject commit 32090b4d4ab70dbfa07f1f2994964f983ab43a69
Subproject commit 4f3fbc0d0df2ee90a760b2d2e2bb8e2126bd92cb

2
extern/zeus vendored

@ -1 +1 @@
Subproject commit ac7d83009dae97a28ba779d00188e3d76e9b9821
Subproject commit e9ec10a3823a3c734e70c99b4aa50ae2a7e7e81f

View File

@ -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})

View File

@ -1,6 +1,7 @@
#include "ImGuiEngine.hpp"
#include <aurora/imgui.h>
#include <cmath>
#include "Runtime/Streams/CMemoryInStream.hpp"
#include "Runtime/Streams/CZipInputStream.hpp"

View File

@ -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