mirror of
https://github.com/Vita3K/Vita3K.git
synced 2026-07-11 01:34:23 +02:00
kernel: Pull out avplayer,auidodev,videodec,fiber state
kernel: Add ObjectStore modules: Support library init function modules: Pull out cpu_protocol vita3k: Rename .h -> .inc io: Remove unneccesary base_tick argument cmake: Folderify modules and kernel
This commit is contained in:
@@ -85,7 +85,7 @@ add_subdirectory(touch)
|
||||
add_subdirectory(util)
|
||||
add_subdirectory(gdbstub)
|
||||
|
||||
add_executable(vita3k MACOSX_BUNDLE main.cpp interface.cpp interface.h performance.cpp)
|
||||
add_executable(vita3k MACOSX_BUNDLE main.cpp interface.cpp interface.h performance.cpp cpu_protocol.h cpu_protocol.cpp)
|
||||
|
||||
target_link_libraries(vita3k PRIVATE app gui modules)
|
||||
if(USE_DISCORD_RICH_PRESENCE)
|
||||
|
||||
@@ -15,12 +15,30 @@
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#pragma once
|
||||
#include "cpu_protocol.h"
|
||||
#include <kernel/functions.h>
|
||||
#include <modules/module_parent.h>
|
||||
|
||||
#include <util/types.h>
|
||||
CPUProtocol::CPUProtocol(HostState &host)
|
||||
: host(&host) {
|
||||
}
|
||||
|
||||
#include <functional>
|
||||
CPUProtocol::~CPUProtocol() {
|
||||
}
|
||||
|
||||
struct HostState;
|
||||
void CPUProtocol::call_svc(CPUState &cpu, uint32_t svc, Address pc, SceUID thread_id) {
|
||||
uint32_t nid = *Ptr<uint32_t>(pc + 4).get(host->mem);
|
||||
::call_import(*host, cpu, nid, thread_id);
|
||||
}
|
||||
|
||||
using ImportVarFactory = std::function<Address(HostState &host)>;
|
||||
Address CPUProtocol::get_watch_memory_addr(Address addr) {
|
||||
return ::get_watch_memory_addr(host->kernel, addr);
|
||||
}
|
||||
|
||||
std::vector<ModuleRegion> &CPUProtocol::get_module_regions() {
|
||||
return host->kernel.module_regions;
|
||||
}
|
||||
|
||||
ExclusiveMonitorPtr CPUProtocol::get_exlusive_monitor() {
|
||||
return host->kernel.exclusive_monitor;
|
||||
}
|
||||
@@ -17,11 +17,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/types.h>
|
||||
#include <cpu/common.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
struct CPUState;
|
||||
struct HostState;
|
||||
|
||||
using ImportFn = std::function<void(HostState &host, CPUState &cpu, SceUID thread_id)>;
|
||||
struct CPUProtocol : public CPUProtocolBase {
|
||||
CPUProtocol(HostState &host);
|
||||
~CPUProtocol();
|
||||
void call_svc(CPUState &cpu, uint32_t svc, Address pc, SceUID thread_id) override;
|
||||
Address get_watch_memory_addr(Address addr) override;
|
||||
std::vector<ModuleRegion> &get_module_regions() override;
|
||||
ExclusiveMonitorPtr get_exlusive_monitor() override;
|
||||
|
||||
private:
|
||||
HostState *host;
|
||||
};
|
||||
@@ -3,8 +3,6 @@ add_library(
|
||||
STATIC
|
||||
include/host/app_util.h
|
||||
include/host/functions.h
|
||||
include/host/import_var.h
|
||||
include/host/import_fn.h
|
||||
include/host/load_self.h
|
||||
include/host/pkg.h
|
||||
include/host/sce_types.h
|
||||
@@ -20,5 +18,5 @@ add_library(
|
||||
)
|
||||
|
||||
target_include_directories(host PUBLIC include ${PSVPFSPARSER_INCLUDE_DIR})
|
||||
target_link_libraries(host PUBLIC psvpfsparser app audio config ctrl dialog ime io kernel miniz net ngs nids np renderer sdl2 touch gdbstub)
|
||||
target_link_libraries(host PUBLIC psvpfsparser app audio config ctrl dialog ime io kernel miniz net ngs nids np renderer sdl2 touch gdbstub codec)
|
||||
target_link_libraries(host PRIVATE elfio::elfio FAT16 vita-toolchain)
|
||||
|
||||
@@ -49,13 +49,13 @@ int write_file(SceUID fd, const void *data, SceSize size, const IOState &io, con
|
||||
int truncate_file(SceUID fd, unsigned long long length, const IOState &io, const char *export_name);
|
||||
SceOff seek_file(SceUID fd, SceOff offset, SceIoSeekMode whence, IOState &io, const char *export_name);
|
||||
SceOff tell_file(IOState &io, const SceUID fd, const char *export_name);
|
||||
int stat_file(IOState &io, const char *file, SceIoStat *statp, const std::wstring &pref_path, SceUInt64 base_tick, const char *export_name, SceUID fd = invalid_fd);
|
||||
int stat_file_by_fd(IOState &io, const SceUID fd, SceIoStat *statp, const std::wstring &pref_path, SceUInt64 base_tick, const char *export_name);
|
||||
int stat_file(IOState &io, const char *file, SceIoStat *statp, const std::wstring &pref_path, const char *export_name, SceUID fd = invalid_fd);
|
||||
int stat_file_by_fd(IOState &io, const SceUID fd, SceIoStat *statp, const std::wstring &pref_path, const char *export_name);
|
||||
int close_file(IOState &io, SceUID fd, const char *export_name);
|
||||
int remove_file(IOState &io, const char *file, const std::wstring &pref_path, const char *export_name);
|
||||
|
||||
SceUID open_dir(IOState &io, const char *path, const std::wstring &pref_path, const char *export_name);
|
||||
SceUID read_dir(IOState &io, SceUID fd, SceIoDirent *dent, const std::wstring &pref_path, const SceUInt64 base_tick, const char *export_name);
|
||||
SceUID read_dir(IOState &io, SceUID fd, SceIoDirent *dent, const std::wstring &pref_path, const char *export_name);
|
||||
int create_dir(IOState &io, const char *dir, int mode, const std::wstring &pref_path, const char *export_name, const bool recursive = false);
|
||||
int close_dir(IOState &io, SceUID fd, const char *export_name);
|
||||
int remove_dir(IOState &io, const char *dir, const std::wstring &pref_path, const char *export_name);
|
||||
|
||||
@@ -448,7 +448,7 @@ SceOff tell_file(IOState &io, const SceUID fd, const char *export_name) {
|
||||
return std_file->second.tell();
|
||||
}
|
||||
|
||||
int stat_file(IOState &io, const char *file, SceIoStat *statp, const std::wstring &pref_path, SceUInt64 base_tick, const char *export_name,
|
||||
int stat_file(IOState &io, const char *file, SceIoStat *statp, const std::wstring &pref_path, const char *export_name,
|
||||
const SceUID fd) {
|
||||
assert(statp != nullptr);
|
||||
|
||||
@@ -547,7 +547,7 @@ int stat_file(IOState &io, const char *file, SceIoStat *statp, const std::wstrin
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stat_file_by_fd(IOState &io, const SceUID fd, SceIoStat *statp, const std::wstring &pref_path, SceUInt64 base_tick, const char *export_name) {
|
||||
int stat_file_by_fd(IOState &io, const SceUID fd, SceIoStat *statp, const std::wstring &pref_path, const char *export_name) {
|
||||
assert(statp != nullptr);
|
||||
memset(statp, '\0', sizeof(SceIoStat));
|
||||
|
||||
@@ -556,7 +556,7 @@ int stat_file_by_fd(IOState &io, const SceUID fd, SceIoStat *statp, const std::w
|
||||
return IO_ERROR(SCE_ERROR_ERRNO_EBADFD);
|
||||
}
|
||||
|
||||
return stat_file(io, std_file->second.get_vita_loc(), statp, pref_path, base_tick, export_name, fd);
|
||||
return stat_file(io, std_file->second.get_vita_loc(), statp, pref_path, export_name, fd);
|
||||
}
|
||||
|
||||
int close_file(IOState &io, const SceUID fd, const char *export_name) {
|
||||
@@ -645,7 +645,7 @@ SceUID open_dir(IOState &io, const char *path, const std::wstring &pref_path, co
|
||||
return fd;
|
||||
}
|
||||
|
||||
SceUID read_dir(IOState &io, const SceUID fd, SceIoDirent *dent, const std::wstring &pref_path, const SceUInt64 base_tick, const char *export_name) {
|
||||
SceUID read_dir(IOState &io, const SceUID fd, SceIoDirent *dent, const std::wstring &pref_path, const char *export_name) {
|
||||
assert(dent != nullptr);
|
||||
|
||||
memset(dent->d_name, '\0', sizeof(dent->d_name));
|
||||
@@ -669,12 +669,12 @@ SceUID read_dir(IOState &io, const SceUID fd, SceIoDirent *dent, const std::wstr
|
||||
const auto file_path = std::string(dir->second.get_vita_loc()) + '/' + d_name_utf8;
|
||||
|
||||
LOG_TRACE_IF(log_file_op, "{}: Reading entry {} of fd: {}", export_name, file_path, log_hex(fd));
|
||||
if (stat_file(io, file_path.c_str(), &dent->d_stat, pref_path, base_tick, export_name) < 0)
|
||||
if (stat_file(io, file_path.c_str(), &dent->d_stat, pref_path, export_name) < 0)
|
||||
return IO_ERROR(SCE_ERROR_ERRNO_EMFILE);
|
||||
else
|
||||
return 1; // move to the next file
|
||||
}
|
||||
return read_dir(io, fd, dent, pref_path, base_tick, export_name);
|
||||
return read_dir(io, fd, dent, pref_path, export_name);
|
||||
}
|
||||
|
||||
return IO_ERROR(SCE_ERROR_ERRNO_EBADFD);
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
add_library(
|
||||
kernel
|
||||
STATIC
|
||||
set(SOURCE_LIST
|
||||
include/kernel/functions.h
|
||||
include/kernel/state.h
|
||||
include/kernel/types.h
|
||||
include/kernel/thread_data_queue.h
|
||||
include/kernel/thread/thread_data_queue.h
|
||||
include/kernel/thread/thread_functions.h
|
||||
include/kernel/thread/thread_state.h
|
||||
include/kernel/thread/sync_primitives.h
|
||||
include/kernel/relocation.h
|
||||
include/kernel/object_store.h
|
||||
src/kernel.cpp
|
||||
src/thread/thread.cpp
|
||||
src/thread/sync_primitives.cpp
|
||||
src/relocation.cpp
|
||||
)
|
||||
|
||||
add_library(
|
||||
kernel
|
||||
STATIC
|
||||
${SOURCE_LIST}
|
||||
)
|
||||
|
||||
target_include_directories(kernel PUBLIC include)
|
||||
target_link_libraries(kernel PUBLIC rtc cpu mem util codec)
|
||||
target_link_libraries(kernel PUBLIC rtc cpu mem util)
|
||||
target_link_libraries(kernel PRIVATE sdl2 miniz vita-toolchain)
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_LIST})
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
// Brought form rpcs3
|
||||
class TypeInfo {
|
||||
friend class ObjectStore;
|
||||
// Global variable for each registered type
|
||||
template <typename T>
|
||||
struct registered {
|
||||
static const uint32_t index;
|
||||
};
|
||||
|
||||
// Increment type counter
|
||||
static uint32_t add_type(uint32_t i) {
|
||||
static std::atomic<uint32_t> g_next{ 0 };
|
||||
|
||||
return g_next.fetch_add(i);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
static inline uint32_t get_index() {
|
||||
return registered<T>::index;
|
||||
}
|
||||
|
||||
static inline uint32_t get_count() {
|
||||
return add_type(0);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const uint32_t TypeInfo::registered<T>::index = TypeInfo::add_type(1);
|
||||
|
||||
class ObjectStore {
|
||||
public:
|
||||
ObjectStore() {}
|
||||
|
||||
~ObjectStore() {}
|
||||
|
||||
template <typename T>
|
||||
T *get() {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
auto it = objs.find(TypeInfo::registered<T>::index);
|
||||
assert(it != objs.end());
|
||||
return reinterpret_cast<T *>(it->second.get());
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
bool create(Args &&... args) {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
objs.emplace(TypeInfo::registered<T>::index, ptr);
|
||||
return true;
|
||||
}
|
||||
template <typename T>
|
||||
void erase() {
|
||||
auto it = objs.find(TypeInfo::registered<T>::index);
|
||||
assert(it != objs.end());
|
||||
objs.erase(it);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex;
|
||||
std::map<uint32_t, std::shared_ptr<void>> objs;
|
||||
};
|
||||
@@ -17,16 +17,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <codec/state.h>
|
||||
#include <cpu/functions.h>
|
||||
#include <kernel/thread/sync_primitives.h>
|
||||
#include <kernel/thread/thread_state.h>
|
||||
#include <kernel/thread_data_queue.h>
|
||||
#include <kernel/types.h>
|
||||
#include <mem/ptr.h>
|
||||
#include <rtc/rtc.h>
|
||||
#include <util/pool.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <kernel/object_store.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
@@ -43,8 +43,6 @@ struct InitialFiber;
|
||||
|
||||
struct CodecEngineBlock;
|
||||
|
||||
typedef std::vector<InitialFiber> InitialFibers;
|
||||
|
||||
typedef std::shared_ptr<SceKernelMemBlockInfo> SceKernelMemBlockInfoPtr;
|
||||
typedef std::map<SceUID, SceKernelMemBlockInfoPtr> Blocks;
|
||||
typedef std::map<SceUID, CodecEngineBlock> CodecEngineBlocks;
|
||||
@@ -61,196 +59,6 @@ typedef std::map<Address, WatchMemory> WatchMemoryAddrs;
|
||||
typedef std::vector<ModuleRegion> ModuleRegions;
|
||||
typedef Pool<CPUState> CPUPool;
|
||||
|
||||
struct MsgPipeData;
|
||||
|
||||
struct WaitingThreadData {
|
||||
ThreadStatePtr thread;
|
||||
int32_t priority;
|
||||
|
||||
// additional fields for each primitive
|
||||
union {
|
||||
struct { // mutex
|
||||
int32_t lock_count;
|
||||
};
|
||||
struct { // semaphore
|
||||
int32_t signal;
|
||||
};
|
||||
struct { // event flags
|
||||
int32_t wait;
|
||||
int32_t flags;
|
||||
};
|
||||
// struct { }; // condvar
|
||||
struct { //msgpipe
|
||||
MsgPipeData *sending_data;
|
||||
};
|
||||
};
|
||||
|
||||
bool operator>(const WaitingThreadData &rhs) const {
|
||||
return priority > rhs.priority;
|
||||
}
|
||||
|
||||
bool operator==(const WaitingThreadData &rhs) const {
|
||||
return thread == rhs.thread;
|
||||
}
|
||||
|
||||
bool operator==(const ThreadStatePtr &rhs) const {
|
||||
return thread == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<ThreadDataQueue<WaitingThreadData>> WaitingThreadQueuePtr;
|
||||
|
||||
// NOTE: uid is copied to sync primitives here for debugging,
|
||||
// not really needed since they are put in std::map's
|
||||
struct SyncPrimitive {
|
||||
SceUID uid;
|
||||
|
||||
uint32_t attr;
|
||||
|
||||
std::mutex mutex;
|
||||
|
||||
char name[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
||||
};
|
||||
|
||||
struct Semaphore : SyncPrimitive {
|
||||
WaitingThreadQueuePtr waiting_threads;
|
||||
int max;
|
||||
int val;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Semaphore> SemaphorePtr;
|
||||
typedef std::map<SceUID, SemaphorePtr> SemaphorePtrs;
|
||||
|
||||
struct Mutex : SyncPrimitive {
|
||||
int init_count;
|
||||
int lock_count;
|
||||
ThreadStatePtr owner;
|
||||
WaitingThreadQueuePtr waiting_threads;
|
||||
Ptr<SceKernelLwMutexWork> workarea;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Mutex> MutexPtr;
|
||||
typedef std::map<SceUID, MutexPtr> MutexPtrs;
|
||||
|
||||
struct EventFlag : SyncPrimitive {
|
||||
WaitingThreadQueuePtr waiting_threads;
|
||||
int flags;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<EventFlag> EventFlagPtr;
|
||||
typedef std::map<SceUID, EventFlagPtr> EventFlagPtrs;
|
||||
|
||||
struct Condvar : SyncPrimitive {
|
||||
struct SignalTarget {
|
||||
enum class Type {
|
||||
Any, // signal any one waiting thread
|
||||
Specific, // signal a specific waiting thread (target_thread)
|
||||
All, // signal all waiting threads
|
||||
} type;
|
||||
|
||||
SceUID thread_id; // for Type::One
|
||||
|
||||
explicit SignalTarget(Type type)
|
||||
: type(type)
|
||||
, thread_id(0) {}
|
||||
SignalTarget(Type type, SceUID thread_id)
|
||||
: type(type)
|
||||
, thread_id(thread_id) {}
|
||||
};
|
||||
|
||||
WaitingThreadQueuePtr waiting_threads;
|
||||
MutexPtr associated_mutex;
|
||||
};
|
||||
typedef std::shared_ptr<Condvar> CondvarPtr;
|
||||
typedef std::map<SceUID, CondvarPtr> CondvarPtrs;
|
||||
|
||||
struct MsgPipeData {
|
||||
std::vector<char> data;
|
||||
SceUID thread_id;
|
||||
size_t read_size;
|
||||
bool waiting_sender;
|
||||
bool notify_at_empty;
|
||||
};
|
||||
|
||||
// Unlimited buffer for now
|
||||
struct MsgPipe : SyncPrimitive {
|
||||
std::mutex recv_mutex;
|
||||
WaitingThreadQueuePtr sender_threads;
|
||||
WaitingThreadQueuePtr reciever_threads;
|
||||
std::list<MsgPipeData> data_buffer;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<MsgPipe> MsgPipePtr;
|
||||
typedef std::map<SceUID, MsgPipePtr> MsgPipePtrs;
|
||||
|
||||
struct WaitingThreadState {
|
||||
std::string name; // for debugging
|
||||
};
|
||||
|
||||
typedef std::map<SceUID, WaitingThreadState> KernelWaitingThreadStates;
|
||||
|
||||
typedef std::shared_ptr<DecoderState> DecoderPtr;
|
||||
typedef std::map<SceUID, DecoderPtr> DecoderStates;
|
||||
|
||||
struct SceAvPlayerMemoryAllocator {
|
||||
uint32_t user_data;
|
||||
|
||||
// All of these should be cast to SceAvPlayerAllocator or SceAvPlayerDeallocator types.
|
||||
Ptr<void> general_allocator;
|
||||
Ptr<void> general_deallocator;
|
||||
Ptr<void> texture_allocator;
|
||||
Ptr<void> texture_deallocator;
|
||||
};
|
||||
|
||||
struct SceAvPlayerFileManager {
|
||||
uint32_t user_data;
|
||||
|
||||
// Cast to SceAvPlayerOpenFile, SceAvPlayerCloseFile, SceAvPlayerReadFile and SceAvPlayerGetFileSize.
|
||||
Ptr<void> open_file;
|
||||
Ptr<void> close_file;
|
||||
Ptr<void> read_file;
|
||||
Ptr<void> file_size;
|
||||
};
|
||||
|
||||
struct SceAvPlayerEventManager {
|
||||
uint32_t user_data;
|
||||
|
||||
// Cast to SceAvPlayerEventCallback.
|
||||
Ptr<void> event_callback;
|
||||
};
|
||||
|
||||
struct PlayerInfoState {
|
||||
PlayerState player;
|
||||
|
||||
// Framebuffer count is defined in info. I'm being safe now and forcing it to 4 (even though its usually 2).
|
||||
constexpr static uint32_t RING_BUFFER_COUNT = 4;
|
||||
|
||||
uint32_t video_buffer_ring_index = 0;
|
||||
uint32_t video_buffer_size = 0;
|
||||
std::array<Ptr<uint8_t>, RING_BUFFER_COUNT> video_buffer;
|
||||
|
||||
uint32_t audio_buffer_ring_index = 0;
|
||||
uint32_t audio_buffer_size = 0;
|
||||
std::array<Ptr<uint8_t>, RING_BUFFER_COUNT> audio_buffer;
|
||||
|
||||
bool do_loop = false;
|
||||
bool paused = false;
|
||||
|
||||
uint64_t last_frame_time = 0;
|
||||
SceAvPlayerMemoryAllocator memory_allocator;
|
||||
SceAvPlayerFileManager file_manager;
|
||||
SceAvPlayerEventManager event_manager;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<PlayerInfoState> PlayerPtr;
|
||||
typedef std::map<SceUID, PlayerPtr> PlayerStates;
|
||||
|
||||
struct MJpegState {
|
||||
bool initialized = false;
|
||||
|
||||
AVCodecContext *decoder{};
|
||||
};
|
||||
|
||||
struct CodecEngineBlock {
|
||||
uint32_t size;
|
||||
int32_t vaddr;
|
||||
@@ -289,14 +97,6 @@ typedef std::map<SceUID, TimerPtr> TimerStates;
|
||||
|
||||
using LoadedSysmodules = std::vector<SceSysmoduleModuleId>;
|
||||
|
||||
struct SceFiber;
|
||||
|
||||
struct InitialFiber {
|
||||
Address start;
|
||||
Address end;
|
||||
SceFiber *fiber;
|
||||
};
|
||||
|
||||
struct WatchMemory {
|
||||
Address start;
|
||||
size_t size;
|
||||
@@ -332,12 +132,10 @@ struct KernelState {
|
||||
CPUBackend cpu_backend;
|
||||
CPUProtocolBase *cpu_protocol;
|
||||
|
||||
InitialFibers initial_fibers;
|
||||
ObjectStore obj_store;
|
||||
|
||||
SceRtcTick start_tick;
|
||||
SceRtcTick base_tick;
|
||||
DecoderPtr mjpeg_state;
|
||||
DecoderStates decoders;
|
||||
PlayerStates players;
|
||||
TimerStates timers;
|
||||
Ptr<uint32_t> process_param;
|
||||
|
||||
|
||||
@@ -17,7 +17,138 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <kernel/state.h>
|
||||
#include <cpu/common.h>
|
||||
#include <kernel/thread/thread_data_queue.h>
|
||||
#include <kernel/types.h>
|
||||
|
||||
struct MsgPipeData;
|
||||
struct KernelState;
|
||||
|
||||
struct WaitingThreadData {
|
||||
ThreadStatePtr thread;
|
||||
int32_t priority;
|
||||
|
||||
// additional fields for each primitive
|
||||
union {
|
||||
struct { // mutex
|
||||
int32_t lock_count;
|
||||
};
|
||||
struct { // semaphore
|
||||
int32_t signal;
|
||||
};
|
||||
struct { // event flags
|
||||
int32_t wait;
|
||||
int32_t flags;
|
||||
};
|
||||
// struct { }; // condvar
|
||||
struct { //msgpipe
|
||||
MsgPipeData *sending_data;
|
||||
};
|
||||
};
|
||||
|
||||
bool operator>(const WaitingThreadData &rhs) const {
|
||||
return priority > rhs.priority;
|
||||
}
|
||||
|
||||
bool operator==(const WaitingThreadData &rhs) const {
|
||||
return thread == rhs.thread;
|
||||
}
|
||||
|
||||
bool operator==(const ThreadStatePtr &rhs) const {
|
||||
return thread == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<ThreadDataQueue<WaitingThreadData>> WaitingThreadQueuePtr;
|
||||
|
||||
// NOTE: uid is copied to sync primitives here for debugging,
|
||||
// not really needed since they are put in std::map's
|
||||
struct SyncPrimitive {
|
||||
SceUID uid;
|
||||
|
||||
uint32_t attr;
|
||||
|
||||
std::mutex mutex;
|
||||
|
||||
char name[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
||||
};
|
||||
|
||||
struct Semaphore : SyncPrimitive {
|
||||
WaitingThreadQueuePtr waiting_threads;
|
||||
int max;
|
||||
int val;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Semaphore> SemaphorePtr;
|
||||
typedef std::map<SceUID, SemaphorePtr> SemaphorePtrs;
|
||||
|
||||
struct Mutex : SyncPrimitive {
|
||||
int init_count;
|
||||
int lock_count;
|
||||
ThreadStatePtr owner;
|
||||
WaitingThreadQueuePtr waiting_threads;
|
||||
Ptr<SceKernelLwMutexWork> workarea;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Mutex> MutexPtr;
|
||||
typedef std::map<SceUID, MutexPtr> MutexPtrs;
|
||||
|
||||
struct EventFlag : SyncPrimitive {
|
||||
WaitingThreadQueuePtr waiting_threads;
|
||||
int flags;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<EventFlag> EventFlagPtr;
|
||||
typedef std::map<SceUID, EventFlagPtr> EventFlagPtrs;
|
||||
|
||||
struct Condvar : SyncPrimitive {
|
||||
struct SignalTarget {
|
||||
enum class Type {
|
||||
Any, // signal any one waiting thread
|
||||
Specific, // signal a specific waiting thread (target_thread)
|
||||
All, // signal all waiting threads
|
||||
} type;
|
||||
|
||||
SceUID thread_id; // for Type::One
|
||||
|
||||
explicit SignalTarget(Type type)
|
||||
: type(type)
|
||||
, thread_id(0) {}
|
||||
SignalTarget(Type type, SceUID thread_id)
|
||||
: type(type)
|
||||
, thread_id(thread_id) {}
|
||||
};
|
||||
|
||||
WaitingThreadQueuePtr waiting_threads;
|
||||
MutexPtr associated_mutex;
|
||||
};
|
||||
typedef std::shared_ptr<Condvar> CondvarPtr;
|
||||
typedef std::map<SceUID, CondvarPtr> CondvarPtrs;
|
||||
|
||||
struct MsgPipeData {
|
||||
std::vector<char> data;
|
||||
SceUID thread_id;
|
||||
size_t read_size;
|
||||
bool waiting_sender;
|
||||
bool notify_at_empty;
|
||||
};
|
||||
|
||||
// Unlimited buffer for now
|
||||
struct MsgPipe : SyncPrimitive {
|
||||
std::mutex recv_mutex;
|
||||
WaitingThreadQueuePtr sender_threads;
|
||||
WaitingThreadQueuePtr reciever_threads;
|
||||
std::list<MsgPipeData> data_buffer;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<MsgPipe> MsgPipePtr;
|
||||
typedef std::map<SceUID, MsgPipePtr> MsgPipePtrs;
|
||||
|
||||
struct WaitingThreadState {
|
||||
std::string name; // for debugging
|
||||
};
|
||||
|
||||
typedef std::map<SceUID, WaitingThreadState> KernelWaitingThreadStates;
|
||||
|
||||
enum class SyncWeight {
|
||||
Light, // lightweight
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
#include "cpu_protocol.h"
|
||||
#include <app/functions.h>
|
||||
#include <app/screen_render.h>
|
||||
#include <config/functions.h>
|
||||
@@ -134,6 +135,8 @@ int main(int argc, char *argv[]) {
|
||||
return HostInitFailed;
|
||||
}
|
||||
|
||||
init_libraries(host);
|
||||
|
||||
GuiState gui;
|
||||
if (!cfg.console)
|
||||
gui::init(gui, host);
|
||||
|
||||
@@ -22,12 +22,13 @@
|
||||
#include "vargs.h"
|
||||
#include "write_return_value.h"
|
||||
|
||||
#include <host/import_fn.h>
|
||||
#include <host/import_var.h>
|
||||
#include <host/state.h>
|
||||
|
||||
#include <microprofile.h>
|
||||
|
||||
using ImportFn = std::function<void(HostState &host, CPUState &cpu, SceUID thread_id)>;
|
||||
using ImportVarFactory = std::function<Address(HostState &host)>;
|
||||
|
||||
// Function returns a value that is written to CPU registers.
|
||||
template <typename Ret, typename... Args, size_t... indices>
|
||||
std::enable_if_t<!std::is_same_v<Ret, void>> call(Ret (*export_fn)(HostState &, SceUID, const char *, Args...), const char *export_name, const ArgsLayout<Args...> &args_layout, const LayoutArgsState &state, std::index_sequence<indices...>, SceUID thread_id, CPUState &cpu, HostState &host) {
|
||||
|
||||
@@ -37,4 +37,4 @@ int stubbed_impl(const char *name, const char *info);
|
||||
#define VAR_BRIDGE_DECL(name) extern const ImportVarFactory import_##name;
|
||||
#define VAR_BRIDGE_IMPL(name) const ImportVarFactory import_##name = export_##name;
|
||||
|
||||
#define VAR_EXPORT(name) Address export_##name(HostState &host)
|
||||
#define VAR_EXPORT(name) Address export_##name(HostState &host)
|
||||
@@ -1,5 +1,5 @@
|
||||
add_library(modules STATIC
|
||||
module_parent.cpp include/modules/module_parent.h
|
||||
set(SOURCE_LIST
|
||||
module_parent.cpp include/modules/module_parent.h include/modules/library_init_list.inc
|
||||
|
||||
SceAVConfig/SceAVConfig.cpp SceAVConfig/SceAVConfig.h
|
||||
SceAppMgr/SceAppMgr.cpp SceAppMgr/SceAppMgr.h
|
||||
@@ -198,6 +198,11 @@ add_library(modules STATIC
|
||||
SceVshBridge/SceVshBridge.cpp SceVshBridge/SceVshBridge.h
|
||||
SceWlanBt/SceWlan.cpp SceWlanBt/SceWlan.h
|
||||
)
|
||||
|
||||
add_library(modules STATIC
|
||||
${SOURCE_LIST}
|
||||
)
|
||||
target_include_directories(modules PUBLIC include)
|
||||
target_link_libraries(modules PRIVATE xxHash::xxhash)
|
||||
target_link_libraries(modules PUBLIC module)
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_LIST})
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "SceAudiodecUser.h"
|
||||
|
||||
#include <codec/state.h>
|
||||
#include <util/lock_and_find.h>
|
||||
|
||||
enum {
|
||||
@@ -30,6 +31,14 @@ enum {
|
||||
SCE_AUDIODEC_MP3_MPEG_VERSION_1,
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<DecoderState> DecoderPtr;
|
||||
typedef std::map<SceUID, DecoderPtr> DecoderStates;
|
||||
|
||||
struct AudiodecState {
|
||||
std::mutex mutex;
|
||||
DecoderStates decoders;
|
||||
};
|
||||
|
||||
struct SceAudiodecInfoAt9 {
|
||||
uint32_t config_data;
|
||||
uint32_t channels;
|
||||
@@ -86,7 +95,8 @@ EXPORT(int, sceAudiodecClearContext) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAudiodecCreateDecoder, SceAudiodecCtrl *ctrl, SceAudiodecCodec codec) {
|
||||
std::lock_guard<std::mutex> lock(host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AudiodecState>();
|
||||
std::lock_guard<std::mutex> lock(state->mutex);
|
||||
|
||||
SceUID handle = host.kernel.get_next_uid();
|
||||
ctrl->handle = handle;
|
||||
@@ -95,7 +105,7 @@ EXPORT(int, sceAudiodecCreateDecoder, SceAudiodecCtrl *ctrl, SceAudiodecCodec co
|
||||
case SCE_AUDIODEC_TYPE_AT9: {
|
||||
SceAudiodecInfoAt9 &info = ctrl->info.get(host.mem)->at9;
|
||||
DecoderPtr decoder = std::make_shared<Atrac9DecoderState>(info.config_data);
|
||||
host.kernel.decoders[handle] = decoder;
|
||||
state->decoders[handle] = decoder;
|
||||
|
||||
ctrl->es_size_max = decoder->get(DecoderQuery::AT9_SUPERFRAME_SIZE);
|
||||
ctrl->pcm_size_max = decoder->get(DecoderQuery::AT9_SAMPLE_PER_SUPERFRAME)
|
||||
@@ -110,7 +120,7 @@ EXPORT(int, sceAudiodecCreateDecoder, SceAudiodecCtrl *ctrl, SceAudiodecCodec co
|
||||
case SCE_AUDIODEC_TYPE_MP3: {
|
||||
SceAudiodecInfoMp3 &info = ctrl->info.get(host.mem)->mp3;
|
||||
DecoderPtr decoder = std::make_shared<Mp3DecoderState>(info.channels);
|
||||
host.kernel.decoders[handle] = decoder;
|
||||
state->decoders[handle] = decoder;
|
||||
|
||||
ctrl->es_size_max = 1441;
|
||||
|
||||
@@ -142,7 +152,8 @@ EXPORT(int, sceAudiodecCreateDecoderResident) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAudiodecDecode, SceAudiodecCtrl *ctrl) {
|
||||
const DecoderPtr &decoder = lock_and_find(ctrl->handle, host.kernel.decoders, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AudiodecState>();
|
||||
const DecoderPtr &decoder = lock_and_find(ctrl->handle, state->decoders, state->mutex);
|
||||
|
||||
DecoderSize size = {};
|
||||
|
||||
@@ -168,8 +179,9 @@ EXPORT(int, sceAudiodecDecodeNStreams) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAudiodecDeleteDecoder, SceAudiodecCtrl *ctrl) {
|
||||
std::lock_guard<std::mutex> lock(host.kernel.mutex);
|
||||
host.kernel.decoders.erase(ctrl->handle);
|
||||
const auto state = host.kernel.obj_store.get<AudiodecState>();
|
||||
std::lock_guard<std::mutex> lock(state->mutex);
|
||||
state->decoders.erase(ctrl->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -192,7 +204,8 @@ EXPORT(int, sceAudiodecGetInternalError) {
|
||||
}
|
||||
|
||||
EXPORT(SceInt32, sceAudiodecInitLibrary, SceUInt32 codecType, SceAudiodecInitParam *pInitParam) {
|
||||
return STUBBED("EMPTY");
|
||||
host.kernel.obj_store.create<AudiodecState>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT(int, sceAudiodecPartlyDecode) {
|
||||
@@ -200,7 +213,8 @@ EXPORT(int, sceAudiodecPartlyDecode) {
|
||||
}
|
||||
|
||||
EXPORT(SceInt32, sceAudiodecTermLibrary, SceUInt32 codecType) {
|
||||
return STUBBED("EMPTY");
|
||||
host.kernel.obj_store.erase<AudiodecState>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
BRIDGE_IMPL(sceAudiodecClearContext)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "SceAvPlayer.h"
|
||||
|
||||
#include <codec/state.h>
|
||||
#include <io/functions.h>
|
||||
#include <kernel/thread/thread_functions.h>
|
||||
#include <util/lock_and_find.h>
|
||||
@@ -40,6 +41,65 @@ typedef uint64_t (*SceAvPlayerGetFileSize)(void *arguments);
|
||||
|
||||
typedef void (*SceAvPlayerEventCallback)(void *arguments, int32_t event_id, int32_t source_id, void *event_data);
|
||||
|
||||
struct PlayerInfoState;
|
||||
typedef std::shared_ptr<PlayerInfoState> PlayerPtr;
|
||||
typedef std::map<SceUID, PlayerPtr> PlayerStates;
|
||||
|
||||
struct AvPlayerState {
|
||||
std::mutex mutex;
|
||||
PlayerStates players;
|
||||
};
|
||||
|
||||
struct SceAvPlayerMemoryAllocator {
|
||||
uint32_t user_data;
|
||||
|
||||
// All of these should be cast to SceAvPlayerAllocator or SceAvPlayerDeallocator types.
|
||||
Ptr<void> general_allocator;
|
||||
Ptr<void> general_deallocator;
|
||||
Ptr<void> texture_allocator;
|
||||
Ptr<void> texture_deallocator;
|
||||
};
|
||||
|
||||
struct SceAvPlayerFileManager {
|
||||
uint32_t user_data;
|
||||
|
||||
// Cast to SceAvPlayerOpenFile, SceAvPlayerCloseFile, SceAvPlayerReadFile and SceAvPlayerGetFileSize.
|
||||
Ptr<void> open_file;
|
||||
Ptr<void> close_file;
|
||||
Ptr<void> read_file;
|
||||
Ptr<void> file_size;
|
||||
};
|
||||
|
||||
struct SceAvPlayerEventManager {
|
||||
uint32_t user_data;
|
||||
|
||||
// Cast to SceAvPlayerEventCallback.
|
||||
Ptr<void> event_callback;
|
||||
};
|
||||
|
||||
struct PlayerInfoState {
|
||||
PlayerState player;
|
||||
|
||||
// Framebuffer count is defined in info. I'm being safe now and forcing it to 4 (even though its usually 2).
|
||||
constexpr static uint32_t RING_BUFFER_COUNT = 4;
|
||||
|
||||
uint32_t video_buffer_ring_index = 0;
|
||||
uint32_t video_buffer_size = 0;
|
||||
std::array<Ptr<uint8_t>, RING_BUFFER_COUNT> video_buffer;
|
||||
|
||||
uint32_t audio_buffer_ring_index = 0;
|
||||
uint32_t audio_buffer_size = 0;
|
||||
std::array<Ptr<uint8_t>, RING_BUFFER_COUNT> audio_buffer;
|
||||
|
||||
bool do_loop = false;
|
||||
bool paused = false;
|
||||
|
||||
uint64_t last_frame_time = 0;
|
||||
SceAvPlayerMemoryAllocator memory_allocator;
|
||||
SceAvPlayerFileManager file_manager;
|
||||
SceAvPlayerEventManager event_manager;
|
||||
};
|
||||
|
||||
enum class DebugLevel {
|
||||
NONE,
|
||||
INFO,
|
||||
@@ -175,7 +235,8 @@ uint run_event_callback(HostState &host, SceUID thread_id, const PlayerPtr playe
|
||||
//end of callback_thread
|
||||
|
||||
EXPORT(int32_t, sceAvPlayerAddSource, SceUID player_handle, Ptr<const char> path) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
|
||||
auto file_path = expand_path(host.io, path.get(host.mem), host.pref_path);
|
||||
if (!fs::exists(file_path) && player_info->file_manager.open_file && player_info->file_manager.close_file && player_info->file_manager.read_file && player_info->file_manager.file_size) {
|
||||
@@ -220,14 +281,17 @@ EXPORT(int32_t, sceAvPlayerAddSource, SceUID player_handle, Ptr<const char> path
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvPlayerClose, SceUID player_handle) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
run_event_callback(host, thread_id, player_info, SCE_AVPLAYER_STATE_STOP, 0, Ptr<void>(0));
|
||||
host.kernel.players.erase(player_handle);
|
||||
std::lock_guard<std::mutex> lock(state->mutex);
|
||||
state->players.erase(player_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT(uint64_t, sceAvPlayerCurrentTime, SceUID player_handle) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
|
||||
return player_info->player.last_timestamp;
|
||||
}
|
||||
@@ -252,7 +316,8 @@ EXPORT(int32_t, sceAvPlayerEnableStream, SceUID player_handle, uint32_t stream_n
|
||||
}
|
||||
|
||||
EXPORT(bool, sceAvPlayerGetAudioData, SceUID player_handle, SceAvPlayerFrameInfo *frame_info) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
|
||||
Ptr<uint8_t> buffer;
|
||||
|
||||
@@ -292,7 +357,8 @@ EXPORT(uint32_t, sceAvPlayerGetStreamInfo, SceUID player_handle, uint stream_no,
|
||||
return SCE_AVPLAYER_ERROR_ILLEGAL_ADDR;
|
||||
}
|
||||
STUBBED("ALWAYS SUSPECTS 2 STREAMS: VIDEO AND AUDIO");
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
auto StreamInfo = stream_info.get(host.mem);
|
||||
if (stream_no == 0) { //suspect always two streams: audio and video //first is video
|
||||
DecoderSize size = player_info->player.get_size();
|
||||
@@ -315,7 +381,8 @@ EXPORT(uint32_t, sceAvPlayerGetStreamInfo, SceUID player_handle, uint stream_no,
|
||||
}
|
||||
|
||||
EXPORT(bool, sceAvPlayerGetVideoData, SceUID player_handle, SceAvPlayerFrameInfo *frame_info) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
|
||||
Ptr<uint8_t> buffer;
|
||||
|
||||
@@ -363,10 +430,12 @@ EXPORT(bool, sceAvPlayerGetVideoDataEx, SceUID player_handle, SceAvPlayerFrameIn
|
||||
}
|
||||
|
||||
EXPORT(SceUID, sceAvPlayerInit, SceAvPlayerInfo *info) {
|
||||
host.kernel.obj_store.create<AvPlayerState>();
|
||||
if (host.cfg.current_config.video_playing) {
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
SceUID player_handle = host.kernel.get_next_uid();
|
||||
PlayerPtr player = std::make_shared<PlayerInfoState>();
|
||||
host.kernel.players[player_handle] = player;
|
||||
state->players[player_handle] = player;
|
||||
|
||||
LOG_TRACE("SceAvPlayerInfo.memory_allocator: user_data:{}, general_allocator:{}, general_deallocator:{}, texture_allocator:{}, texture_deallocator:{}",
|
||||
log_hex(info->memory_allocator.user_data), log_hex(info->memory_allocator.general_allocator.address()), log_hex(info->memory_allocator.general_deallocator.address()),
|
||||
@@ -393,7 +462,8 @@ EXPORT(SceUID, sceAvPlayerInit, SceAvPlayerInfo *info) {
|
||||
}
|
||||
|
||||
EXPORT(bool, sceAvPlayerIsActive, SceUID player_handle) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
|
||||
return !player_info->player.video_playing.empty();
|
||||
}
|
||||
@@ -403,7 +473,8 @@ EXPORT(int, sceAvPlayerJumpToTime) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvPlayerPause, SceUID player_handle) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
player_info->paused = true;
|
||||
run_event_callback(host, thread_id, player_info, SCE_AVPLAYER_STATE_PAUSE, 0, Ptr<void>(0));
|
||||
return 0;
|
||||
@@ -414,7 +485,8 @@ EXPORT(int, sceAvPlayerPostInit) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvPlayerResume, SceUID player_handle) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
if (!player_info->paused) {
|
||||
run_event_callback(host, thread_id, player_info, SCE_AVPLAYER_STATE_PLAY, 0, Ptr<void>(0));
|
||||
}
|
||||
@@ -423,7 +495,8 @@ EXPORT(int, sceAvPlayerResume, SceUID player_handle) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvPlayerSetLooping, SceUID player_handle, bool do_loop) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
player_info->do_loop = do_loop;
|
||||
|
||||
return STUBBED("LOOPING NOT IMPLEMENTED");
|
||||
@@ -434,7 +507,8 @@ EXPORT(int, sceAvPlayerSetTrickSpeed) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvPlayerStart, SceUID player_handle) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, state->mutex);
|
||||
if (!player_info->player.videos_queue.empty()) {
|
||||
player_info->player.pop_video();
|
||||
}
|
||||
@@ -443,7 +517,8 @@ EXPORT(int, sceAvPlayerStart, SceUID player_handle) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvPlayerStop, SceUID player_handle) {
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, host.kernel.players, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<AvPlayerState>();
|
||||
const PlayerPtr &player_info = lock_and_find(player_handle, state->players, host.kernel.mutex);
|
||||
player_info->player.free_video();
|
||||
run_event_callback(host, thread_id, player_info, SCE_AVPLAYER_STATE_STOP, 0, Ptr<void>(0));
|
||||
return 0;
|
||||
|
||||
@@ -24,10 +24,27 @@
|
||||
|
||||
const static int DEFAULT_FIBER_STACK_SIZE = 4096;
|
||||
|
||||
InitialFiber *_findIntialFiber(KernelState &kernel, Address sp) {
|
||||
struct InitialFiber {
|
||||
Address start;
|
||||
Address end;
|
||||
SceFiber *fiber;
|
||||
};
|
||||
|
||||
typedef std::vector<InitialFiber> InitialFibers;
|
||||
|
||||
struct FiberState {
|
||||
InitialFibers initial_fibers;
|
||||
};
|
||||
|
||||
LIBRARY_INIT_IMPL(SceFiber) {
|
||||
host.kernel.obj_store.create<FiberState>();
|
||||
}
|
||||
LIBRARY_INIT_REGISTER(SceFiber)
|
||||
|
||||
InitialFiber *_findIntialFiber(FiberState &state, Address sp) {
|
||||
// TODO use interval tree
|
||||
// TODO destroy initial fibers
|
||||
for (auto &ifiber : kernel.initial_fibers) {
|
||||
for (auto &ifiber : state.initial_fibers) {
|
||||
// stack adress is descending
|
||||
if (ifiber.start <= sp && sp <= ifiber.end) {
|
||||
return &ifiber;
|
||||
@@ -36,22 +53,23 @@ InitialFiber *_findIntialFiber(KernelState &kernel, Address sp) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void _resetFiber(HostState &host, SceFiber *fiber) {
|
||||
auto ifiber = _findIntialFiber(host.kernel, fiber->cpu->get_sp());
|
||||
void _resetFiber(FiberState &state, MemState &mem, SceFiber *fiber) {
|
||||
auto ifiber = _findIntialFiber(state, fiber->cpu->get_sp());
|
||||
assert(ifiber);
|
||||
const auto cpu = fiber->cpu;
|
||||
*fiber = *ifiber->fiber;
|
||||
fiber->cpu = cpu;
|
||||
*fiber->cpu = *ifiber->fiber->cpu;
|
||||
memset(Ptr<void>(ifiber->start).get(host.mem), 0xCC, ifiber->end - ifiber->start);
|
||||
memset(Ptr<void>(ifiber->start).get(mem), 0xCC, ifiber->end - ifiber->start);
|
||||
}
|
||||
|
||||
int _fiberSwitch(HostState &host, const ThreadStatePtr thread, SceFiber *fiber, CPUContext &backup_cpu_context, SceUInt32 argOnRunTo, Ptr<SceUInt32> argOnRun, bool reset) {
|
||||
const auto state = host.kernel.obj_store.get<FiberState>();
|
||||
backup_cpu_context = save_context(*thread->cpu);
|
||||
|
||||
bool suspended = false;
|
||||
if (fiber->addrContext == 0 && reset) {
|
||||
_resetFiber(host, fiber);
|
||||
_resetFiber(*state, host.mem, fiber);
|
||||
} else if (fiber->entry.address() == fiber->cpu->get_pc()) {
|
||||
fiber->cpu->cpu_registers[1] = argOnRunTo;
|
||||
} else {
|
||||
@@ -70,6 +88,7 @@ int _fiberSwitch(HostState &host, const ThreadStatePtr thread, SceFiber *fiber,
|
||||
}
|
||||
|
||||
void _initializeFiber(HostState &host, const ThreadStatePtr thread, SceFiber *fiber, const char *name, Ptr<SceFiberEntry> entry, SceUInt32 argOnInitialize, Ptr<void> addrContext, SceSize sizeContext, SceFiberOptParam *params) {
|
||||
const auto state = host.kernel.obj_store.get<FiberState>();
|
||||
fiber->entry = entry;
|
||||
strncpy(fiber->name, name, 32);
|
||||
fiber->argOnInitialize = argOnInitialize;
|
||||
@@ -101,7 +120,7 @@ void _initializeFiber(HostState &host, const ThreadStatePtr thread, SceFiber *fi
|
||||
ifiber.start = addrContext.address();
|
||||
ifiber.end = addrContext.address() + sizeContext;
|
||||
ifiber.fiber = fiberCopy;
|
||||
host.kernel.initial_fibers.push_back(ifiber);
|
||||
state->initial_fibers.push_back(ifiber);
|
||||
}
|
||||
|
||||
EXPORT(int, _sceFiberAttachContextAndRun, SceFiber *fiber, Address addrContext, SceSize sizeContext, SceUInt32 argOnRunTo, Ptr<SceUInt32> argOnRun) {
|
||||
@@ -218,6 +237,7 @@ EXPORT(int, sceFiberRenameSelf) {
|
||||
}
|
||||
|
||||
EXPORT(SceInt32, sceFiberReturnToThread, SceUInt32 argOnReturn, Ptr<SceUInt32> argOnRun) {
|
||||
const auto state = host.kernel.obj_store.get<FiberState>();
|
||||
const ThreadStatePtr thread = lock_and_find(thread_id, host.kernel.threads, host.kernel.mutex);
|
||||
auto fiber = thread->fiber.cast<SceFiber>().get(host.mem);
|
||||
(*thread->fiber.cast<SceFiber>().get(host.mem)->cpu) = save_context(*thread->cpu);
|
||||
@@ -225,7 +245,7 @@ EXPORT(SceInt32, sceFiberReturnToThread, SceUInt32 argOnReturn, Ptr<SceUInt32> a
|
||||
|
||||
Address previousArgOnRun = thread->cpu_context.cpu_registers[2];
|
||||
if (fiber->addrContext == 0) {
|
||||
_resetFiber(host, fiber);
|
||||
_resetFiber(*state, host.mem, fiber);
|
||||
} else if (previousArgOnRun) {
|
||||
*(Ptr<SceUInt32>(previousArgOnRun).get(host.mem)) = argOnReturn;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <module/module.h>
|
||||
#include <modules/module_parent.h>
|
||||
|
||||
#define SCE_FIBER_CONTEXT_MINIMUM_SIZE 512
|
||||
|
||||
@@ -49,6 +50,7 @@ typedef struct SceFiber {
|
||||
CPUContext *cpu;
|
||||
} SceFiber;
|
||||
|
||||
LIBRARY_INIT_DECL(SceFiber)
|
||||
BRIDGE_DECL(_sceFiberAttachContextAndRun)
|
||||
BRIDGE_DECL(_sceFiberAttachContextAndSwitch)
|
||||
BRIDGE_DECL(_sceFiberInitializeImpl)
|
||||
|
||||
@@ -51,11 +51,11 @@ EXPORT(int, _sceIoDread, const SceUID fd, SceIoDirent *dir) {
|
||||
if (dir == nullptr) {
|
||||
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_ADDR);
|
||||
}
|
||||
return read_dir(host.io, fd, dir, host.pref_path, host.kernel.base_tick.tick, export_name);
|
||||
return read_dir(host.io, fd, dir, host.pref_path, export_name);
|
||||
}
|
||||
|
||||
EXPORT(int, _sceIoGetstat, const char *file, SceIoStat *stat) {
|
||||
return stat_file(host.io, file, stat, host.pref_path, host.kernel.base_tick.tick, export_name);
|
||||
return stat_file(host.io, file, stat, host.pref_path, export_name);
|
||||
}
|
||||
|
||||
EXPORT(int, _sceIoGetstatAsync) {
|
||||
@@ -63,7 +63,7 @@ EXPORT(int, _sceIoGetstatAsync) {
|
||||
}
|
||||
|
||||
EXPORT(int, _sceIoGetstatByFd, const SceUID fd, SceIoStat *stat) {
|
||||
return stat_file_by_fd(host.io, fd, stat, host.pref_path, host.kernel.base_tick.tick, export_name);
|
||||
return stat_file_by_fd(host.io, fd, stat, host.pref_path, export_name);
|
||||
}
|
||||
|
||||
EXPORT(int, _sceIoIoctl) {
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
|
||||
#include <codec/state.h>
|
||||
|
||||
typedef std::shared_ptr<DecoderState> DecoderPtr;
|
||||
|
||||
struct MJpegState {
|
||||
bool initialized = false;
|
||||
DecoderPtr decoder;
|
||||
};
|
||||
|
||||
struct SceJpegMJpegInitInfo {
|
||||
uint32_t size;
|
||||
int32_t decoder_count;
|
||||
@@ -54,13 +61,12 @@ EXPORT(int, sceJpegDecodeMJpeg) {
|
||||
|
||||
EXPORT(int, sceJpegDecodeMJpegYCbCr, const uint8_t *jpeg_data, uint32_t jpeg_size,
|
||||
uint8_t *output, uint32_t output_size, int mode, void *buffer, uint32_t buffer_size) {
|
||||
if (!host.kernel.mjpeg_state)
|
||||
return -1;
|
||||
const auto state = host.kernel.obj_store.get<MJpegState>();
|
||||
|
||||
DecoderSize size = {};
|
||||
|
||||
host.kernel.mjpeg_state->send(jpeg_data, jpeg_size);
|
||||
host.kernel.mjpeg_state->receive(output, &size);
|
||||
state->decoder->send(jpeg_data, jpeg_size);
|
||||
state->decoder->receive(output, &size);
|
||||
|
||||
// Top 16 bits = width, bottom 16 bits = height.
|
||||
return (size.width << 16u) | size.height;
|
||||
@@ -71,20 +77,19 @@ EXPORT(int, sceJpegDeleteSplitDecoder) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceJpegFinishMJpeg) {
|
||||
host.kernel.mjpeg_state.reset();
|
||||
host.kernel.obj_store.erase<MJpegState>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT(int, sceJpegGetOutputInfo, const uint8_t *jpeg_data, uint32_t jpeg_size,
|
||||
int32_t format, int32_t mode, SceJpegOutputInfo *output) {
|
||||
if (!host.kernel.mjpeg_state)
|
||||
return -1;
|
||||
const auto state = host.kernel.obj_store.get<MJpegState>();
|
||||
|
||||
DecoderSize size = {};
|
||||
|
||||
host.kernel.mjpeg_state->send(jpeg_data, jpeg_size);
|
||||
host.kernel.mjpeg_state->receive(nullptr, &size);
|
||||
state->decoder->send(jpeg_data, jpeg_size);
|
||||
state->decoder->receive(nullptr, &size);
|
||||
|
||||
output->width = size.width;
|
||||
output->height = size.height;
|
||||
@@ -96,13 +101,17 @@ EXPORT(int, sceJpegGetOutputInfo, const uint8_t *jpeg_data, uint32_t jpeg_size,
|
||||
|
||||
// TODO: Decoder options are ignored for the time being.
|
||||
EXPORT(int, sceJpegInitMJpeg, int32_t decoder_count) {
|
||||
host.kernel.mjpeg_state = std::make_shared<MjpegDecoderState>();
|
||||
host.kernel.obj_store.create<MJpegState>();
|
||||
const auto state = host.kernel.obj_store.get<MJpegState>();
|
||||
state->decoder = std::make_shared<MjpegDecoderState>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT(int, sceJpegInitMJpegWithParam, const SceJpegMJpegInitInfo *info) {
|
||||
host.kernel.mjpeg_state = std::make_shared<MjpegDecoderState>();
|
||||
host.kernel.obj_store.create<MJpegState>();
|
||||
const auto state = host.kernel.obj_store.get<MJpegState>();
|
||||
state->decoder = std::make_shared<MjpegDecoderState>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <module/module.h>
|
||||
#include <modules/module_parent.h>
|
||||
|
||||
BRIDGE_DECL(sceJpegCreateSplitDecoder)
|
||||
BRIDGE_DECL(sceJpegCsc)
|
||||
|
||||
@@ -397,7 +397,7 @@ EXPORT(int, sceIoGetstatAsync) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceIoGetstatByFd, const SceUID fd, SceIoStat *stat) {
|
||||
return stat_file_by_fd(host.io, fd, stat, host.pref_path, host.kernel.base_tick.tick, export_name);
|
||||
return stat_file_by_fd(host.io, fd, stat, host.pref_path, export_name);
|
||||
}
|
||||
|
||||
EXPORT(int, sceIoIoctl) {
|
||||
|
||||
@@ -16,9 +16,17 @@
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "SceVideodecUser.h"
|
||||
|
||||
#include <codec/state.h>
|
||||
#include <util/lock_and_find.h>
|
||||
|
||||
typedef std::shared_ptr<DecoderState> DecoderPtr;
|
||||
typedef std::map<SceUID, DecoderPtr> DecoderStates;
|
||||
|
||||
struct VideodecState {
|
||||
std::mutex mutex;
|
||||
DecoderStates decoders;
|
||||
};
|
||||
|
||||
enum SceVideodecType {
|
||||
SCE_VIDEODEC_TYPE_HW_AVCDEC = 0x1001
|
||||
};
|
||||
@@ -119,11 +127,11 @@ struct SceAvcdecArrayPicture {
|
||||
|
||||
EXPORT(int, sceAvcdecCreateDecoder, uint32_t codec_type, SceAvcdecCtrl *decoder, const SceAvcdecQueryDecoderInfo *query) {
|
||||
assert(codec_type == SCE_VIDEODEC_TYPE_HW_AVCDEC);
|
||||
|
||||
const auto state = host.kernel.obj_store.get<VideodecState>();
|
||||
SceUID handle = host.kernel.get_next_uid();
|
||||
decoder->handle = handle;
|
||||
|
||||
host.kernel.decoders[handle] = std::make_shared<H264DecoderState>(query->horizontal, query->vertical);
|
||||
state->decoders[handle] = std::make_shared<H264DecoderState>(query->horizontal, query->vertical);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -145,7 +153,8 @@ EXPORT(int, sceAvcdecCscInternal) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvcdecDecode, SceAvcdecCtrl *decoder, const SceAvcdecAu *au, SceAvcdecArrayPicture *picture) {
|
||||
const DecoderPtr &decoder_info = lock_and_find(decoder->handle, host.kernel.decoders, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<VideodecState>();
|
||||
const DecoderPtr &decoder_info = lock_and_find(decoder->handle, state->decoders, state->mutex);
|
||||
|
||||
H264DecoderOptions options = {};
|
||||
options.pts_upper = au->pts.upper;
|
||||
@@ -183,14 +192,16 @@ EXPORT(int, sceAvcdecDecodeAuNongameapp) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvcdecDecodeAvailableSize, SceAvcdecCtrl *decoder) {
|
||||
const DecoderPtr &decoder_info = lock_and_find(decoder->handle, host.kernel.decoders, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<VideodecState>();
|
||||
const DecoderPtr &decoder_info = lock_and_find(decoder->handle, state->decoders, state->mutex);
|
||||
|
||||
return H264DecoderState::buffer_size(
|
||||
{ decoder_info->get(DecoderQuery::WIDTH), decoder_info->get(DecoderQuery::HEIGHT) });
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvcdecDecodeFlush, SceAvcdecCtrl *decoder) {
|
||||
const DecoderPtr &decoder_info = lock_and_find(decoder->handle, host.kernel.decoders, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<VideodecState>();
|
||||
const DecoderPtr &decoder_info = lock_and_find(decoder->handle, state->decoders, state->mutex);
|
||||
|
||||
decoder_info->flush();
|
||||
|
||||
@@ -226,7 +237,8 @@ EXPORT(int, sceAvcdecDecodeSetUserDataSei1FieldMemSizeNongameapp) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvcdecDecodeStop, SceAvcdecCtrl *decoder, SceAvcdecArrayPicture *picture) {
|
||||
const DecoderPtr &decoder_info = lock_and_find(decoder->handle, host.kernel.decoders, host.kernel.mutex);
|
||||
const auto state = host.kernel.obj_store.get<VideodecState>();
|
||||
const DecoderPtr &decoder_info = lock_and_find(decoder->handle, state->decoders, state->mutex);
|
||||
|
||||
uint8_t *output = picture->pPicture.get(host.mem)[0].get(host.mem)->frame.pPicture[0].cast<uint8_t>().get(host.mem);
|
||||
decoder_info->receive(output);
|
||||
@@ -243,7 +255,9 @@ EXPORT(int, sceAvcdecDecodeWithWorkPicture) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceAvcdecDeleteDecoder, SceAvcdecCtrl *decoder) {
|
||||
host.kernel.decoders.erase(decoder->handle);
|
||||
const auto state = host.kernel.obj_store.get<VideodecState>();
|
||||
std::lock_guard<std::mutex> lock(state->mutex);
|
||||
state->decoders.erase(decoder->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -366,11 +380,13 @@ EXPORT(int, sceM4vdecQueryDecoderMemSizeInternal) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceVideodecInitLibrary) {
|
||||
return STUBBED("EMPTY");
|
||||
host.kernel.obj_store.create<VideodecState>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT(int, sceVideodecInitLibraryInternal) {
|
||||
return UNIMPLEMENTED();
|
||||
host.kernel.obj_store.create<VideodecState>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT(int, sceVideodecInitLibraryNongameapp) {
|
||||
@@ -415,7 +431,8 @@ EXPORT(int, sceVideodecSetConfigInternal) {
|
||||
}
|
||||
|
||||
EXPORT(int, sceVideodecTermLibrary) {
|
||||
return UNIMPLEMENTED();
|
||||
host.kernel.obj_store.erase<VideodecState>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
BRIDGE_IMPL(sceAvcdecCreateDecoder)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
LIBRARY(SceFiber)
|
||||
@@ -24,8 +24,8 @@
|
||||
struct CPUState;
|
||||
struct HostState;
|
||||
struct KernelState;
|
||||
struct CPUDepInject;
|
||||
|
||||
void init_libraries(HostState &host);
|
||||
void call_import(HostState &host, CPUState &cpu, uint32_t nid, SceUID thread_id);
|
||||
bool load_module(HostState &host, SceSysmoduleModuleId module_id);
|
||||
Address resolve_export(KernelState &kernel, uint32_t nid);
|
||||
@@ -41,22 +41,15 @@ struct VarExport {
|
||||
constexpr int var_exports_size =
|
||||
#define NID(name, nid)
|
||||
#define VAR_NID(name, nid) 1 +
|
||||
#include <nids/nids.h>
|
||||
#include <nids/nids.inc>
|
||||
0;
|
||||
#undef VAR_NID
|
||||
#undef NID
|
||||
|
||||
const std::array<VarExport, var_exports_size> &get_var_exports();
|
||||
|
||||
// TODO move to module
|
||||
struct CPUProtocol : public CPUProtocolBase {
|
||||
CPUProtocol(HostState &host);
|
||||
~CPUProtocol();
|
||||
void call_svc(CPUState &cpu, uint32_t svc, Address pc, SceUID thread_id) override;
|
||||
Address get_watch_memory_addr(Address addr) override;
|
||||
std::vector<ModuleRegion> &get_module_regions() override;
|
||||
ExclusiveMonitorPtr get_exlusive_monitor() override;
|
||||
using LibraryInitFn = std::function<void(HostState &host)>;
|
||||
|
||||
private:
|
||||
HostState *host;
|
||||
};
|
||||
#define LIBRARY_INIT_DECL(name) void export_library_init_##name(HostState &host);
|
||||
#define LIBRARY_INIT_IMPL(name) void export_library_init_##name(HostState &host)
|
||||
#define LIBRARY_INIT_REGISTER(name) extern const LibraryInitFn import_library_init_##name = export_library_init_##name;
|
||||
@@ -18,8 +18,6 @@
|
||||
#include <modules/module_parent.h>
|
||||
|
||||
#include <cpu/functions.h>
|
||||
#include <host/import_fn.h>
|
||||
#include <host/import_var.h>
|
||||
#include <host/load_self.h>
|
||||
#include <host/state.h>
|
||||
#include <io/device.h>
|
||||
@@ -36,9 +34,13 @@
|
||||
|
||||
static constexpr bool LOG_UNK_NIDS_ALWAYS = false;
|
||||
|
||||
#define LIBRARY(name) extern const LibraryInitFn import_library_init_##name;
|
||||
#include <modules/library_init_list.inc>
|
||||
#undef LIBRARY
|
||||
|
||||
#define VAR_NID(name, nid) extern const ImportVarFactory import_##name;
|
||||
#define NID(name, nid) extern const ImportFn import_##name;
|
||||
#include <nids/nids.h>
|
||||
#include <nids/nids.inc>
|
||||
#undef NID
|
||||
#undef VAR_NID
|
||||
|
||||
@@ -50,7 +52,7 @@ static ImportFn resolve_import(uint32_t nid) {
|
||||
#define NID(name, nid) \
|
||||
case nid: \
|
||||
return import_##name;
|
||||
#include <nids/nids.h>
|
||||
#include <nids/nids.inc>
|
||||
#undef NID
|
||||
#undef VAR_NID
|
||||
}
|
||||
@@ -67,7 +69,7 @@ const std::array<VarExport, var_exports_size> &get_var_exports() {
|
||||
import_##name, \
|
||||
#name \
|
||||
},
|
||||
#include <nids/nids.h>
|
||||
#include <nids/nids.inc>
|
||||
#undef VAR_NID
|
||||
#undef NID
|
||||
};
|
||||
@@ -212,26 +214,8 @@ bool load_module(HostState &host, SceSysmoduleModuleId module_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CPUProtocol::CPUProtocol(HostState &host)
|
||||
: host(&host) {
|
||||
void init_libraries(HostState &host) {
|
||||
#define LIBRARY(name) import_library_init_##name(host);
|
||||
#include <modules/library_init_list.inc>
|
||||
#undef LIBRARY
|
||||
}
|
||||
|
||||
CPUProtocol::~CPUProtocol() {
|
||||
}
|
||||
|
||||
void CPUProtocol::call_svc(CPUState &cpu, uint32_t svc, Address pc, SceUID thread_id) {
|
||||
uint32_t nid = *Ptr<uint32_t>(pc + 4).get(host->mem);
|
||||
::call_import(*host, cpu, nid, thread_id);
|
||||
}
|
||||
|
||||
Address CPUProtocol::get_watch_memory_addr(Address addr) {
|
||||
return ::get_watch_memory_addr(host->kernel, addr);
|
||||
}
|
||||
|
||||
std::vector<ModuleRegion> &CPUProtocol::get_module_regions() {
|
||||
return host->kernel.module_regions;
|
||||
}
|
||||
|
||||
ExclusiveMonitorPtr CPUProtocol::get_exlusive_monitor() {
|
||||
return host->kernel.exclusive_monitor;
|
||||
}
|
||||
@@ -33,4 +33,5 @@ add_library(
|
||||
src/scheduler.cpp)
|
||||
|
||||
target_include_directories(ngs PUBLIC include)
|
||||
target_link_libraries(ngs PRIVATE util mem kernel codec cpu)
|
||||
target_link_libraries(ngs PUBLIC codec)
|
||||
target_link_libraries(ngs PRIVATE util mem kernel cpu)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <ngs/system.h>
|
||||
|
||||
#include <codec/state.h>
|
||||
#include <ngs/system.h>
|
||||
|
||||
namespace ngs::atrac9 {
|
||||
enum {
|
||||
|
||||
@@ -2,7 +2,7 @@ add_library(
|
||||
nids
|
||||
STATIC
|
||||
include/nids/functions.h
|
||||
include/nids/nids.h
|
||||
include/nids/nids.inc
|
||||
include/nids/types.h
|
||||
src/nids.cpp
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#define VAR_NID(name, nid) extern const char name_##name[] = #name;
|
||||
#define NID(name, nid) extern const char name_##name[] = #name;
|
||||
#include <nids/nids.h>
|
||||
#include <nids/nids.inc>
|
||||
#undef NID
|
||||
#undef VAR_NID
|
||||
|
||||
@@ -14,7 +14,7 @@ const char *import_name(uint32_t nid) {
|
||||
#define NID(name, nid) \
|
||||
case nid: \
|
||||
return name_##name;
|
||||
#include <nids/nids.h>
|
||||
#include <nids/nids.inc>
|
||||
#undef NID
|
||||
#undef VAR_NID
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user