mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-07 20:11:46 -04:00
Aurora DVD support (#43)
* Aurora DVD support * Remove commented code * Restore STUB_LOG
This commit is contained in:
+5
-1
@@ -10,6 +10,10 @@ set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
|
||||
endif ()
|
||||
set(AURORA_ENABLE_DVD ON CACHE BOOL "Enable DVD API support" FORCE)
|
||||
add_subdirectory(extern/aurora EXCLUDE_FROM_ALL)
|
||||
|
||||
option(DUSK_BUILD_WARNINGS "If off, compiler warnings will be suppressed")
|
||||
@@ -80,7 +84,7 @@ target_include_directories(game_debug PUBLIC
|
||||
extern
|
||||
${CMAKE_SOURCE_DIR}/build/${DUSK_TP_VERSION}/include
|
||||
build/${DUSK_TP_VERSION}/include)
|
||||
target_link_libraries(game_debug PUBLIC aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os)
|
||||
target_link_libraries(game_debug PUBLIC aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd)
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
add_library(game SHARED ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${SSYSTEM_FILES} ${JSYSTEM_FILES} ${REL_FILES} ${DUSK_FILES} ${DOLPHIN_FILES})
|
||||
|
||||
@@ -62,4 +62,9 @@ cmake -B build/dusk -GNinja
|
||||
ninja -C build/dusk
|
||||
```
|
||||
|
||||
After building the executable, extract the original game files to a folder named `data` in the same folder as the executable.
|
||||
#### Running
|
||||
Pass the disc image as a positional argument. Supported formats: ISO (GCM), RVZ, WIA, WBFS, CISO, GCZ
|
||||
```sh
|
||||
build/dusk/dusk /path/to/game.rvz
|
||||
```
|
||||
If no path is specified, Dusk defaults to `game.iso` in the current working directory.
|
||||
|
||||
Vendored
+1
-1
Submodule extern/aurora updated: 2b4bac1b9e...45ed0aa9d2
@@ -1335,7 +1335,6 @@ set(DUSK_FILES
|
||||
src/dusk/extras.cpp
|
||||
src/dusk/globals.cpp
|
||||
#src/dusk/m_Do_ext_dusk.cpp
|
||||
src/dusk/dvd_emu.cpp
|
||||
src/dusk/imgui/imgui.hpp
|
||||
src/dusk/imgui/processes.cpp
|
||||
src/dusk/imgui/camera.cpp
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#ifndef DOLPHIN_DVD_EMU_H
|
||||
#define DOLPHIN_DVD_EMU_H
|
||||
|
||||
#include "dolphin/types.h"
|
||||
#include <string>
|
||||
|
||||
// PC-Emulation der DVD-Funktionen
|
||||
namespace DvdEmu {
|
||||
|
||||
// Basis-Pfad zum Datenordner (relativ zur .exe)
|
||||
void setBasePath(const char* path);
|
||||
const char* getBasePath();
|
||||
|
||||
// Konvertiert GameCube-Pfad zu PC-Pfad
|
||||
// z.B. "/res/Object/LogoUs.arc" -> "C:/Games/Dusk/data/res/Object/LogoUs.arc"
|
||||
std::string convertPath(const char* gcPath);
|
||||
|
||||
// Prüft ob Datei existiert
|
||||
bool fileExists(const char* gcPath);
|
||||
|
||||
// Lädt Datei komplett in Speicher
|
||||
// Gibt Pointer zurück, Größe wird in outSize geschrieben
|
||||
// Caller muss Speicher mit free() freigeben
|
||||
void* loadFile(const char* gcPath, u32* outSize, void* heap = nullptr);
|
||||
|
||||
// Lädt Datei in vorhandenen Buffer
|
||||
// Gibt gelesene Bytes zurück
|
||||
u32 loadFileToBuffer(const char* gcPath, void* buffer, u32 bufferSize, u32 offset = 0);
|
||||
|
||||
// Datei-Größe abfragen
|
||||
u32 getFileSize(const char* gcPath);
|
||||
|
||||
} // namespace DvdEmu
|
||||
|
||||
// Ersatz für DVDConvertPathToEntrynum
|
||||
// Gibt einen "Fake" Entry-Number zurück (Hash des Pfads) oder -1 wenn nicht gefunden
|
||||
s32 DVDConvertPathToEntrynum_Emu(const char* path);
|
||||
|
||||
// Speichert Pfad für Entry-Number (für späteres Laden)
|
||||
void DVDRegisterPath(s32 entryNum, const char* path);
|
||||
|
||||
// Holt Pfad für Entry-Number
|
||||
const char* DVDGetPathForEntry(s32 entryNum);
|
||||
|
||||
#endif // DOLPHIN_DVD_EMU_H
|
||||
@@ -240,7 +240,7 @@ inline void* operator new[](size_t, JKRHeapToken, void* where) {
|
||||
#define JKR_NEW new (JKRHeapToken::Dummy)
|
||||
#define JKR_NEW_ARGS(...) new (JKRHeapToken::Dummy, __VA_ARGS__ )
|
||||
#define JKR_DELETE(expr) jkrDelete(expr)
|
||||
#define JKR_DELETE_ARRAY(expr) delete[] (expr)
|
||||
#define JKR_DELETE_ARRAY(expr) jkrDeleteArray(expr)
|
||||
#define JKR_HEAP_TOKEN , JKRHeapToken::Dummy
|
||||
#define JKR_HEAP_TOKEN_PARAM , JKRHeapToken
|
||||
#else
|
||||
@@ -261,7 +261,7 @@ void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, int alignment);
|
||||
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment);
|
||||
|
||||
void operator delete(void* ptr JKR_HEAP_TOKEN_PARAM);
|
||||
void operator delete[](void* ptr);
|
||||
void operator delete[](void* ptr JKR_HEAP_TOKEN_PARAM);
|
||||
|
||||
#if TARGET_PC
|
||||
template<typename T>
|
||||
@@ -281,6 +281,10 @@ inline void jkrDelete(void* ptr) {
|
||||
|
||||
operator delete(ptr, JKRHeapToken::Dummy);
|
||||
}
|
||||
|
||||
static void jkrDeleteArray(void* ptr) {
|
||||
operator delete[](ptr, JKRHeapToken::Dummy);
|
||||
}
|
||||
#endif
|
||||
|
||||
void JKRDefaultMemoryErrorRoutine(void* heap, u32 size, int alignment);
|
||||
|
||||
@@ -38,7 +38,7 @@ void J2DScreen::clean() {
|
||||
mFontRes = NULL;
|
||||
|
||||
if (mNameTable != NULL) {
|
||||
JKR_DELETE_ARRAY(mNameTable->getResNameTable());
|
||||
JKR_DELETE_ARRAY(const_cast<ResNTAB*>(mNameTable->getResNameTable()));
|
||||
JKR_DELETE(mNameTable);
|
||||
mNameTable = NULL;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
#include "JSystem/JGadget/binary.h"
|
||||
#include "JSystem/JGadget/define.h"
|
||||
#include "global.h"
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
@@ -593,14 +593,6 @@ void* operator new[](size_t size) {
|
||||
return JKRHeap::alloc(size, 4, NULL);
|
||||
}
|
||||
#else
|
||||
void* operator new[](size_t size) {
|
||||
return fallback_alloc(size, 0, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size, const std::nothrow_t&) noexcept {
|
||||
return fallback_alloc(size, 0, false);
|
||||
}
|
||||
|
||||
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM) {
|
||||
void* mem = JKRHeap::alloc(size, alignof(max_align_t), NULL);
|
||||
if (mem == NULL) {
|
||||
@@ -654,7 +646,7 @@ void operator delete[](void* ptr) {
|
||||
JKRHeap::free(ptr, NULL);
|
||||
}
|
||||
#else
|
||||
void operator delete[](void* ptr) {
|
||||
void operator delete[](void* ptr JKR_HEAP_TOKEN_PARAM) {
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
JKRHeap* heap = JKRHeap::findFromRoot(ptr);
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
#include "dusk/dvd_emu.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
#include "dolphin/os.h"
|
||||
#include "dusk/logging.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#define PATH_SEP '\\'
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#define PATH_SEP '/'
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
s32 g_nextEntryNum = 1;
|
||||
|
||||
// Lazy-init to avoid crash during DLL static initialization
|
||||
std::string& g_basePath() {
|
||||
static std::string instance = "data";
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::unordered_map<s32, std::string>& getEntryPaths() {
|
||||
static std::unordered_map<s32, std::string> instance;
|
||||
return instance;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace DvdEmu {
|
||||
|
||||
void setBasePath(const char* path) {
|
||||
#ifdef _WIN32
|
||||
char exePath[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, exePath, MAX_PATH);
|
||||
|
||||
// Get the directory of the .exe
|
||||
char* lastSlash = strrchr(exePath, '\\');
|
||||
if (lastSlash) {
|
||||
*lastSlash = '\0';
|
||||
}
|
||||
|
||||
// exeDir + "/" + path
|
||||
g_basePath() = exePath;
|
||||
g_basePath() += PATH_SEP;
|
||||
g_basePath() += path;
|
||||
#else
|
||||
g_basePath() = path;
|
||||
#endif
|
||||
|
||||
DuskLog.debug("[DvdEmu] Base path set to: %s\n", g_basePath().c_str());
|
||||
}
|
||||
|
||||
const char* getBasePath() {
|
||||
return g_basePath().c_str();
|
||||
}
|
||||
|
||||
std::string convertPath(const char* gcPath) {
|
||||
std::string result = g_basePath();
|
||||
|
||||
// Skip leading slashes
|
||||
const char* p = gcPath;
|
||||
while (*p == '/' || *p == '\\')
|
||||
p++;
|
||||
|
||||
result += PATH_SEP;
|
||||
|
||||
// Append path, converting slashes
|
||||
while (*p) {
|
||||
if (*p == '/' || *p == '\\') {
|
||||
result += PATH_SEP;
|
||||
} else {
|
||||
result += *p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool fileExists(const char* gcPath) {
|
||||
std::string fullPath = convertPath(gcPath);
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD attrib = GetFileAttributesA(fullPath.c_str());
|
||||
bool exists = (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
#else
|
||||
struct stat st;
|
||||
bool exists = (stat(fullPath.c_str(), &st) == 0 && S_ISREG(st.st_mode));
|
||||
#endif
|
||||
|
||||
if (exists) {
|
||||
DuskLog.info("[DvdEmu] FOUND: {}", gcPath);
|
||||
} else {
|
||||
DuskLog.warn("[DvdEmu] MISSING: {}", gcPath);
|
||||
}
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
u32 getFileSize(const char* gcPath) {
|
||||
std::string fullPath = convertPath(gcPath);
|
||||
FILE* f = fopen(fullPath.c_str(), "rb");
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
u32 size = (u32)ftell(f);
|
||||
fclose(f);
|
||||
return size;
|
||||
}
|
||||
|
||||
void* loadFile(const char* gcPath, u32* outSize, void* heap) {
|
||||
std::string fullPath = convertPath(gcPath);
|
||||
|
||||
DuskLog.debug("[DvdEmu] Loading request: '{}'", gcPath);
|
||||
|
||||
FILE* f = fopen(fullPath.c_str(), "rb");
|
||||
if (!f) {
|
||||
DuskLog.error("[DvdEmu] Failed to open file at physical path: {}", fullPath.c_str());
|
||||
if (outSize)
|
||||
*outSize = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
u32 size = (u32)ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
// Allocate with 32-byte alignment (matching GameCube)
|
||||
void* data;
|
||||
#ifdef _WIN32
|
||||
data = _aligned_malloc(size, 32);
|
||||
#else
|
||||
data = aligned_alloc(32, (size + 31) & ~31);
|
||||
#endif
|
||||
|
||||
if (!data) {
|
||||
DuskLog.fatal("[DvdEmu] Failed to allocate {} bytes for {}", size, gcPath);
|
||||
fclose(f);
|
||||
if (outSize)
|
||||
*outSize = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 bytesRead = (u32)fread(data, 1, size, f);
|
||||
fclose(f);
|
||||
|
||||
if (bytesRead != size) {
|
||||
DuskLog.fatal("[DvdEmu] Read error: expected {}, got {} for {}", size, bytesRead,
|
||||
gcPath);
|
||||
}
|
||||
|
||||
if (outSize)
|
||||
*outSize = bytesRead;
|
||||
|
||||
DuskLog.info("[DvdEmu] Loaded {} ({} bytes)", gcPath, bytesRead);
|
||||
return data;
|
||||
}
|
||||
|
||||
u32 loadFileToBuffer(const char* gcPath, void* buffer, u32 bufferSize, u32 offset) {
|
||||
std::string fullPath = convertPath(gcPath);
|
||||
|
||||
FILE* f = fopen(fullPath.c_str(), "rb");
|
||||
if (!f) {
|
||||
DuskLog.error("[DvdEmu] Failed to open file for buffer load: {}", fullPath.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (offset > 0) {
|
||||
fseek(f, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
u32 bytesRead = (u32)fread(buffer, 1, bufferSize, f);
|
||||
fclose(f);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
} // namespace DvdEmu
|
||||
|
||||
// Entry-Number System (emulates DVD's entry system)
|
||||
|
||||
s32 DVDConvertPathToEntrynum_Emu(const char* path) {
|
||||
if (!DvdEmu::fileExists(path)) {
|
||||
printf("[DVD] Error: File not found for entrynum conversion: %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check if already registered
|
||||
for (const auto& pair : getEntryPaths()) {
|
||||
if (pair.second == path) {
|
||||
return pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign new entry number
|
||||
s32 entryNum = g_nextEntryNum++;
|
||||
getEntryPaths()[entryNum] = path;
|
||||
|
||||
return entryNum;
|
||||
}
|
||||
|
||||
void DVDRegisterPath(s32 entryNum, const char* path) {
|
||||
getEntryPaths()[entryNum] = path;
|
||||
}
|
||||
|
||||
const char* DVDGetPathForEntry(s32 entryNum) {
|
||||
auto it = getEntryPaths().find(entryNum);
|
||||
if (it != getEntryPaths().end()) {
|
||||
return it->second.c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <condition_variable>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <dusk/dvd_emu.h>
|
||||
#include <dusk/logging.h>
|
||||
|
||||
|
||||
@@ -1169,123 +1168,6 @@ void AIStopDMA(void) {
|
||||
STUB_LOG();
|
||||
}
|
||||
|
||||
#pragma mark DVD
|
||||
#include <dolphin/dvd.h>
|
||||
s32 DVDCancel(volatile DVDCommandBlock* block) {
|
||||
STUB_LOG();
|
||||
return 0;
|
||||
}
|
||||
s32 DVDCancel(DVDCommandBlock* block) {
|
||||
STUB_LOG();
|
||||
return 0;
|
||||
}
|
||||
BOOL DVDChangeDir(const char* dirName) {
|
||||
STUB_LOG();
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DVDCheckDisk(void) {
|
||||
STUB_LOG();
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DVDClose(DVDFileInfo* fileInfo) {
|
||||
STUB_LOG();
|
||||
return TRUE;
|
||||
}
|
||||
int DVDCloseDir(DVDDir* dir) {
|
||||
STUB_LOG();
|
||||
return 0;
|
||||
}
|
||||
s32 DVDConvertPathToEntrynum(const char* pathPtr) {
|
||||
return DVDConvertPathToEntrynum_Emu(pathPtr);
|
||||
}
|
||||
BOOL DVDFastOpen(s32 entrynum, DVDFileInfo* fileInfo) {
|
||||
const char* path = DVDGetPathForEntry(entrynum);
|
||||
if (!path) {
|
||||
OSReport("[DVD] DVDFastOpen: no path for entry %d\n", entrynum);
|
||||
return FALSE;
|
||||
}
|
||||
u32 fileSize = DvdEmu::getFileSize(path);
|
||||
if (fileSize == 0) {
|
||||
OSReport("[DVD] DVDFastOpen: file not found or empty for entry %d (%s)\n", entrynum, path);
|
||||
return FALSE;
|
||||
}
|
||||
// Repurpose startAddr to store entrynum for later DVDReadPrio lookups
|
||||
fileInfo->startAddr = (u32)entrynum;
|
||||
fileInfo->length = fileSize;
|
||||
fileInfo->callback = NULL;
|
||||
fileInfo->cb.state = 0;
|
||||
return TRUE;
|
||||
}
|
||||
s32 DVDGetCommandBlockStatus(const DVDCommandBlock* block) {
|
||||
STUB_LOG();
|
||||
return 0;
|
||||
}
|
||||
DVDDiskID* DVDGetCurrentDiskID(void) {
|
||||
STUB_LOG();
|
||||
return NULL;
|
||||
}
|
||||
s32 DVDGetDriveStatus(void) {
|
||||
STUB_LOG();
|
||||
return 0;
|
||||
}
|
||||
void DVDInit(void) {
|
||||
STUB_LOG();
|
||||
}
|
||||
BOOL DVDOpen(const char* fileName, DVDFileInfo* fileInfo) {
|
||||
s32 entryNum = DVDConvertPathToEntrynum(fileName);
|
||||
if (entryNum < 0) {
|
||||
OSReport("[DVD] DVDOpen: file not found: %s\n", fileName);
|
||||
return FALSE;
|
||||
}
|
||||
return DVDFastOpen(entryNum, fileInfo);
|
||||
}
|
||||
int DVDOpenDir(const char* dirName, DVDDir* dir) {
|
||||
STUB_LOG();
|
||||
return 0;
|
||||
}
|
||||
BOOL DVDReadAsyncPrio(DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset,
|
||||
DVDCallback callback, s32 prio) {
|
||||
// Synchronous read, then invoke callback with result
|
||||
s32 entryNum = (s32)fileInfo->startAddr;
|
||||
const char* path = DVDGetPathForEntry(entryNum);
|
||||
if (!path) {
|
||||
OSReport("[DVD] DVDReadAsyncPrio: no path for entry %d\n", entryNum);
|
||||
if (callback) callback(-1, fileInfo);
|
||||
return FALSE;
|
||||
}
|
||||
u32 bytesRead = DvdEmu::loadFileToBuffer(path, addr, (u32)length, (u32)offset);
|
||||
if (callback) {
|
||||
callback((s32)bytesRead, fileInfo);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
int DVDReadDir(DVDDir* dir, DVDDirEntry* dirent) {
|
||||
STUB_LOG();
|
||||
return 0;
|
||||
}
|
||||
s32 DVDReadPrio(DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset, s32 prio) {
|
||||
s32 entryNum = (s32)fileInfo->startAddr;
|
||||
const char* path = DVDGetPathForEntry(entryNum);
|
||||
if (!path) {
|
||||
OSReport("[DVD] DVDReadPrio: no path for entry %d\n", entryNum);
|
||||
return -1;
|
||||
}
|
||||
u32 bytesRead = DvdEmu::loadFileToBuffer(path, addr, (u32)length, (u32)offset);
|
||||
return (s32)bytesRead;
|
||||
}
|
||||
|
||||
void DVDReadAbsAsyncForBS(void* a, struct bb2struct* b, int c, int d, void (*e)()) {
|
||||
STUB_LOG();
|
||||
}
|
||||
|
||||
void DVDReadDiskID(void* a, DVDDiskID* b, void (*c)()) {
|
||||
STUB_LOG();
|
||||
}
|
||||
|
||||
void DVDReset() {
|
||||
STUB_LOG();
|
||||
}
|
||||
|
||||
#pragma mark GX
|
||||
#include <dolphin/gx.h>
|
||||
|
||||
|
||||
+25
-25
@@ -44,13 +44,14 @@
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "SSystem/SComponent/c_API.h"
|
||||
#include "dusk/dvd_emu.h"
|
||||
#include "dusk/dusk.h"
|
||||
#include "dusk/logging.h"
|
||||
|
||||
#include <aurora/aurora.h>
|
||||
#include <aurora/event.h>
|
||||
#include <aurora/main.h>
|
||||
#include <aurora/dvd.h>
|
||||
#include <dolphin/dvd.h>
|
||||
|
||||
#include "cxxopts.hpp"
|
||||
|
||||
@@ -67,7 +68,7 @@ const int audioHeapSize = 0x14D800;
|
||||
#endif
|
||||
|
||||
// =========================================================================
|
||||
// LOAD_COPYDATE - PC Version using DvdEmu
|
||||
// LOAD_COPYDATE - PC Version
|
||||
// =========================================================================
|
||||
#define COPYDATE_PATH "/str/Final/Release/COPYDATE"
|
||||
|
||||
@@ -75,33 +76,26 @@ s32 LOAD_COPYDATE(void*) {
|
||||
char buffer[32];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
u32 size = 0;
|
||||
void* data = DvdEmu::loadFile(COPYDATE_PATH, &size, nullptr);
|
||||
DVDFileInfo fi;
|
||||
if (DVDOpen(COPYDATE_PATH, &fi)) {
|
||||
u32 readLen = (fi.length < sizeof(buffer) - 1) ? fi.length : sizeof(buffer) - 1;
|
||||
// DVDReadPrio requires 32-byte aligned buffer and length rounded up to 32
|
||||
u32 alignedLen = (readLen + 31) & ~31;
|
||||
alignas(32) char readBuf[64];
|
||||
DVDReadPrio(&fi, readBuf, alignedLen, 0, 2);
|
||||
DVDClose(&fi);
|
||||
|
||||
// Fallback: Try root if not found
|
||||
if (!data) {
|
||||
data = DvdEmu::loadFile("/COPYDATE", &size, nullptr);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
u32 copyLen = (size < sizeof(buffer) - 1) ? size : sizeof(buffer) - 1;
|
||||
memcpy(buffer, data, copyLen);
|
||||
buffer[copyLen] = '\0';
|
||||
|
||||
#ifdef _WIN32
|
||||
_aligned_free(data);
|
||||
#else
|
||||
free(data);
|
||||
#endif
|
||||
memcpy(buffer, readBuf, readLen);
|
||||
buffer[readLen] = '\0';
|
||||
} else {
|
||||
strcpy(buffer, "PC PORT BUILD");
|
||||
OSReport("Warning: COPYDATE file not found at %s\n", COPYDATE_PATH);
|
||||
DuskLog.warn("COPYDATE file not found at {}", COPYDATE_PATH);
|
||||
}
|
||||
|
||||
memcpy(mDoMain::COPYDATE_STRING, buffer, sizeof(mDoMain::COPYDATE_STRING) - 1);
|
||||
mDoMain::COPYDATE_STRING[sizeof(mDoMain::COPYDATE_STRING) - 1] = '\0';
|
||||
|
||||
OS_REPORT("\x1b[36mCOPYDATE=[%s]\n\x1b[m", mDoMain::COPYDATE_STRING);
|
||||
DuskLog.info("COPYDATE=[{}]", mDoMain::COPYDATE_STRING);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -203,8 +197,11 @@ int game_main(int argc, char* argv[]) {
|
||||
|
||||
arg_options.add_options()
|
||||
("l,log-level", "Log level from " + std::to_string(AuroraLogLevel::LOG_DEBUG) + " to " + std::to_string(AuroraLogLevel::LOG_FATAL), cxxopts::value<uint8_t>()->default_value("0"))
|
||||
("h,help", "Print usage");
|
||||
("h,help", "Print usage")
|
||||
("dvd", "Path to DVD image file", cxxopts::value<std::string>()->default_value("game.iso"));
|
||||
|
||||
arg_options.parse_positional({"dvd"});
|
||||
arg_options.positional_help("<dvd-image>");
|
||||
arg_options.allow_unrecognised_options();
|
||||
|
||||
parsed_arg_options = arg_options.parse(argc, argv);
|
||||
@@ -234,10 +231,13 @@ int game_main(int argc, char* argv[]) {
|
||||
|
||||
auroraInfo = aurora_initialize(argc, argv, &config);
|
||||
|
||||
OSInit();
|
||||
const auto& dvd_path = parsed_arg_options["dvd"].as<std::string>();
|
||||
DuskLog.info("Loading DVD image: {}", dvd_path);
|
||||
if (!aurora_dvd_open(dvd_path.c_str())) {
|
||||
DuskLog.fatal("Failed to open DVD image: {}", dvd_path);
|
||||
}
|
||||
|
||||
// 3. Init DVD Emulation
|
||||
DvdEmu::setBasePath("data");
|
||||
OSInit();
|
||||
|
||||
mDoMain::sPowerOnTime = OSGetTime();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user