mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 00:33:06 +00:00
Initial commit
This commit is contained in:
commit
147188b143
427 files changed
+205923
No files matched your search
+4108
File diff suppressed because it is too large.
Load diff
+311
@@ -0,0 +1,311 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_AGC_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_AGC_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
#include "common/subsystems.h"
|
||||
#include "kernel/eventQueue.h"
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
struct Shader;
|
||||
struct ShaderRegister;
|
||||
|
||||
struct SizeAlign {
|
||||
uint64_t m_size;
|
||||
size_t m_align;
|
||||
};
|
||||
|
||||
struct MemoryRange {
|
||||
void* m_base;
|
||||
uint64_t m_size;
|
||||
};
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Graphics);
|
||||
|
||||
void GraphicsDbgDumpDcb(const char* type, uint32_t num_dw, uint32_t* cmd_buffer);
|
||||
|
||||
namespace Gen5 {
|
||||
|
||||
struct CommandBuffer;
|
||||
struct Label;
|
||||
|
||||
int KYTY_SYSV_ABI GraphicsInit(uint32_t* state, uint32_t ver);
|
||||
void* KYTY_SYSV_ABI GraphicsGetRegisterDefaults2(uint32_t ver);
|
||||
void* KYTY_SYSV_ABI GraphicsGetRegisterDefaults2Internal(uint32_t ver);
|
||||
int KYTY_SYSV_ABI GraphicsCreateShader(Shader** dst, void* header, const volatile void* code);
|
||||
int KYTY_SYSV_ABI GraphicsUnknownGetFusedShaderSize(SizeAlign* dst, const Shader* front,
|
||||
const Shader* back);
|
||||
int KYTY_SYSV_ABI GraphicsUnknownFuseShaderHalves(Shader* fused_result, const Shader* front,
|
||||
const Shader* back, void* scratch_mem);
|
||||
int KYTY_SYSV_ABI GraphicsSetCxRegIndirectPatchSetAddress(uint32_t* cmd,
|
||||
const volatile ShaderRegister* regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetShRegIndirectPatchSetAddress(uint32_t* cmd,
|
||||
const volatile ShaderRegister* regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetUcRegIndirectPatchSetAddress(uint32_t* cmd,
|
||||
const volatile ShaderRegister* regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetCxRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_t num_regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetShRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_t num_regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetUcRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_t num_regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetCxRegIndirectPatchAddRegisters(uint32_t* cmd, uint32_t num_regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetShRegIndirectPatchAddRegisters(uint32_t* cmd, uint32_t num_regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetUcRegIndirectPatchAddRegisters(uint32_t* cmd, uint32_t num_regs);
|
||||
int KYTY_SYSV_ABI GraphicsCreatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_regs,
|
||||
const Shader* hs, const Shader* gs, uint32_t prim_type);
|
||||
int KYTY_SYSV_ABI GraphicsUpdatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_regs,
|
||||
uint32_t prim_type);
|
||||
int KYTY_SYSV_ABI GraphicsCreateInterpolantMapping(ShaderRegister* regs, const Shader* gs,
|
||||
const Shader* ps);
|
||||
int KYTY_SYSV_ABI GraphicsGetDataPacketPayloadAddress(uint32_t** addr, uint32_t* cmd, int type);
|
||||
int KYTY_SYSV_ABI GraphicsGetDataPacketPayloadRange(MemoryRange* range, uint32_t* cmd, int type);
|
||||
int KYTY_SYSV_ABI GraphicsWriteDataPatchSetAddressOrOffset(uint32_t* cmd,
|
||||
uint64_t address_or_offset);
|
||||
int KYTY_SYSV_ABI GraphicsUnknownJumpPatchSetTarget(uint32_t* cmd, const volatile uint32_t* target,
|
||||
uint32_t size_in_dwords);
|
||||
int KYTY_SYSV_ABI GraphicsJumpPatchSetTarget(uint32_t* cmd, const volatile uint32_t* target,
|
||||
uint32_t size_in_dwords);
|
||||
int KYTY_SYSV_ABI GraphicsSuspendPoint();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsUnknownQj7QZpgr9Uw(CommandBuffer* buf, uint32_t mode,
|
||||
uint32_t value);
|
||||
uint64_t KYTY_SYSV_ABI GraphicsGetIsTrinityMode();
|
||||
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDriverGetDefaultOwner();
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDriverGetResourceRegistrationMaxNameLength();
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDriverInitResourceRegistration();
|
||||
uint32_t KYTY_SYSV_ABI
|
||||
GraphicsDriverQueryResourceRegistrationUserMemoryRequirements(uint64_t* size_in_bytes);
|
||||
int KYTY_SYSV_ABI GraphicsDriverRegisterOwner();
|
||||
int KYTY_SYSV_ABI GraphicsDriverRegisterResource();
|
||||
int KYTY_SYSV_ABI GraphicsDriverUnregisterResource();
|
||||
int KYTY_SYSV_ABI GraphicsDriverRegisterWorkloadStream(uint32_t stream_id, const void* stream);
|
||||
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsCbNop(CommandBuffer* buf, uint32_t size_in_dwords);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsCbNopGetSize(uint32_t size_in_dwords);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsCbDispatch(CommandBuffer* buf, uint32_t thread_group_x,
|
||||
uint32_t thread_group_y, uint32_t thread_group_z,
|
||||
uint32_t modifier);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsCbDispatchGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsCbBranch(CommandBuffer* buf, uint8_t mode, uint8_t compare_function,
|
||||
const volatile uint64_t* compare_addr, uint64_t mask,
|
||||
uint64_t reference, uint8_t cache_policy1,
|
||||
const volatile uint32_t* buffer1, uint32_t size_in_dwords1,
|
||||
uint8_t cache_policy2, const volatile uint32_t* buffer2,
|
||||
uint32_t size_in_dwords2);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsCbSetShRegisterRangeDirect(CommandBuffer* buf, uint32_t offset,
|
||||
const uint32_t* values,
|
||||
uint32_t num_values);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsCbSetShRegisterRangeDirectGetSize(uint32_t num_values);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsCbSetShRegistersDirect(CommandBuffer* buf,
|
||||
const volatile ShaderRegister* regs,
|
||||
uint32_t num_regs);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsCbReleaseMem(CommandBuffer* buf, uint8_t action, uint16_t gcr_cntl,
|
||||
uint8_t dst, uint8_t cache_policy,
|
||||
const volatile Label* address, uint8_t data_sel,
|
||||
uint64_t data, uint16_t gds_offset, uint16_t gds_size,
|
||||
uint8_t interrupt, uint32_t interrupt_ctx_id);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsCbQueueEndOfPipeActionGetSize();
|
||||
int KYTY_SYSV_ABI GraphicsDebugRaiseException(uint32_t exception_id);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbResetQueue(CommandBuffer* buf, uint32_t op);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbResetQueue(CommandBuffer* buf, uint32_t op, uint32_t state);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbWaitUntilSafeForRendering(CommandBuffer* buf,
|
||||
uint32_t video_out_handle,
|
||||
uint32_t display_buffer_index);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetWorkloadsActive(CommandBuffer* buf, uint32_t stream_id,
|
||||
const uint32_t* workload_ids,
|
||||
uint32_t workload_count);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetWorkloadComplete(CommandBuffer* buf, uint32_t stream_id,
|
||||
uint32_t workload_id);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetShRegisterDirect(CommandBuffer* buf, ShaderRegister reg);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetCxRegisterDirect(CommandBuffer* buf, ShaderRegister reg);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbSetCxRegisterDirectGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetUcRegisterDirect(CommandBuffer* buf, ShaderRegister reg);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetCxRegistersIndirect(CommandBuffer* buf,
|
||||
const volatile ShaderRegister* regs,
|
||||
uint32_t num_regs);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetShRegistersIndirect(CommandBuffer* buf,
|
||||
const volatile ShaderRegister* regs,
|
||||
uint32_t num_regs);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetUcRegistersIndirect(CommandBuffer* buf,
|
||||
const volatile ShaderRegister* regs,
|
||||
uint32_t num_regs);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetIndexSize(CommandBuffer* buf, uint8_t index_size,
|
||||
uint8_t cache_policy);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetIndexBuffer(CommandBuffer* buf, uint64_t index_addr);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetIndexCount(CommandBuffer* buf, uint32_t index_count);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetNumInstances(CommandBuffer* buf, uint32_t num_instances);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbSetNumInstancesGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDrawIndex(CommandBuffer* buf, uint32_t index_count,
|
||||
const volatile void* index_addr, uint64_t modifier);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbDrawIndexGetSize();
|
||||
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDrawIndexMultiInstanced(CommandBuffer* buf, uint32_t index_count,
|
||||
const volatile void* index_addr,
|
||||
const volatile void* object_ids,
|
||||
uint32_t instance_count,
|
||||
uint64_t modifier);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbDrawIndexMultiInstancedGetSize();
|
||||
int KYTY_SYSV_ABI GraphicsUnknownIkfdtRIqCE(uint32_t* cmd, uint64_t arg1,
|
||||
const volatile uint32_t* target,
|
||||
uint32_t size_in_dwords, uint64_t arg4, uint64_t arg5);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDrawIndexAuto(CommandBuffer* buf, uint32_t index_count,
|
||||
uint64_t modifier);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbDrawIndexAutoGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDrawIndexOffset(CommandBuffer* buf, uint32_t index_offset,
|
||||
uint32_t index_count, uint64_t modifier);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbDrawIndexOffsetGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetBaseIndirectArgs(CommandBuffer* buf, uint32_t shader_type,
|
||||
const volatile void* indirect_base_addr);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDrawIndirect(CommandBuffer* buf, uint32_t data_offset_in_bytes,
|
||||
uint64_t modifier);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbDrawIndirectGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDrawIndexIndirect(CommandBuffer* buf,
|
||||
uint32_t data_offset_in_bytes,
|
||||
uint64_t modifier);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDrawIndexIndirectMulti(
|
||||
CommandBuffer* buf, uint32_t data_offset_in_bytes, uint32_t count_indirect,
|
||||
uint32_t max_count_or_count, const volatile void* count_addr, uint32_t stride_in_bytes,
|
||||
uint64_t modifier);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDispatchIndirect(CommandBuffer* buf,
|
||||
uint32_t data_offset_in_bytes, uint32_t flags);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbDispatchIndirectGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbEventWrite(CommandBuffer* buf, uint8_t event_type,
|
||||
const volatile void* address);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbAcquireMem(CommandBuffer* buf, uint8_t engine, uint32_t cb_db_op,
|
||||
uint32_t gcr_cntl, const volatile void* base,
|
||||
uint64_t size_bytes, uint32_t poll_cycles);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbAcquireMemGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbEventWrite(CommandBuffer* buf, uint8_t event_type,
|
||||
const volatile void* address);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbAcquireMem(CommandBuffer* buf, uint32_t gcr_cntl,
|
||||
const volatile void* base, uint64_t size_bytes,
|
||||
uint32_t poll_cycles);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsAcbAcquireMemGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbCondExec(CommandBuffer* buf, const volatile uint32_t* address,
|
||||
uint32_t num_dwords);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsAcbCondExecGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbWaitRegMem(CommandBuffer* buf, uint8_t size,
|
||||
uint8_t compare_function, uint8_t cache_policy,
|
||||
const volatile void* address, uint64_t reference,
|
||||
uint64_t mask, uint32_t poll_cycles);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbDmaData(CommandBuffer* buf, uint8_t engine, uint8_t dst,
|
||||
uint8_t dst_cache_policy, uint64_t dst_address_or_offset,
|
||||
uint8_t src, uint8_t src_cache_policy,
|
||||
uint64_t src_address_or_offset_or_immediate,
|
||||
uint32_t num_bytes, uint8_t wait_for_previous,
|
||||
uint8_t write_confirm, uint8_t block_engine);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbCopyData(CommandBuffer* buf, uint8_t dst,
|
||||
uint8_t dst_cache_policy, uint64_t dst_address,
|
||||
uint8_t src, uint8_t src_cache_policy,
|
||||
uint64_t src_address_or_immediate, uint8_t item_size,
|
||||
uint8_t write_confirm);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbDispatchIndirect(CommandBuffer* buf,
|
||||
const volatile void* indirect_args,
|
||||
uint32_t modifier);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbWriteData(CommandBuffer* buf, uint8_t dst, uint8_t cache_policy,
|
||||
uint64_t address_or_offset, const void* data,
|
||||
uint32_t num_dwords, uint8_t increment,
|
||||
uint8_t write_confirm);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbSetMarker(CommandBuffer* buf, const char* str, uint32_t color);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbPushMarker(CommandBuffer* buf, const char* str, uint32_t color);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsAcbPopMarker(CommandBuffer* buf);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbStallCommandBufferParser(CommandBuffer* buf);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbCopyData(CommandBuffer* buf, uint8_t dst,
|
||||
uint8_t dst_cache_policy, uint64_t dst_address,
|
||||
uint8_t src, uint8_t src_cache_policy,
|
||||
uint64_t src_address_or_immediate, uint8_t item_size,
|
||||
uint8_t write_confirm);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbDmaData(CommandBuffer* buf, uint8_t engine, uint8_t dst,
|
||||
uint8_t dst_cache_policy, uint64_t dst_address_or_offset,
|
||||
uint8_t src, uint8_t src_cache_policy,
|
||||
uint64_t src_address_or_offset_or_immediate,
|
||||
uint32_t num_bytes, uint8_t wait_for_previous,
|
||||
uint8_t write_confirm, uint8_t block_engine);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbJump(CommandBuffer* buf, uint8_t mode, uint8_t cache_policy,
|
||||
const uint32_t* target, uint32_t size_in_dwords);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbJumpGetSize();
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbRewindGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbRewind(CommandBuffer* buf, uint32_t initial_state);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbCondExec(CommandBuffer* buf, const volatile uint32_t* address,
|
||||
uint32_t num_dwords);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbCondExecGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetPredication(CommandBuffer* buf, uint8_t condition, uint8_t op,
|
||||
uint8_t wait_op, const volatile void* address,
|
||||
uint32_t count_in_dwords);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsUnknownKRzWekV120(CommandBuffer* buf, uint32_t arg1, uint32_t arg2,
|
||||
uint32_t arg3);
|
||||
int KYTY_SYSV_ABI GraphicsDmaDataPatchSetDstAddressOrOffset(uint32_t* cmd,
|
||||
uint64_t dst_address_or_offset);
|
||||
int KYTY_SYSV_ABI GraphicsDmaDataPatchSetSrcAddressOrOffsetOrImmediate(
|
||||
uint32_t* cmd, uint64_t src_address_or_offset_or_immediate);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsGetPacketSize(uint32_t* packet);
|
||||
int KYTY_SYSV_ABI GraphicsSetPacketPredication(uint32_t* packet, uint32_t predication);
|
||||
int KYTY_SYSV_ABI GraphicsSetRangePredication(uint32_t* start, const volatile uint32_t* end,
|
||||
uint32_t predication);
|
||||
int KYTY_SYSV_ABI GraphicsCondExecPatchSetEnd(uint32_t* cmd, const volatile uint32_t* buffer);
|
||||
int KYTY_SYSV_ABI GraphicsCondExecPatchSetCommandAddress(uint32_t* cmd,
|
||||
const volatile uint32_t* command);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbWriteData(CommandBuffer* buf, uint8_t dst, uint8_t cache_policy,
|
||||
uint64_t address_or_offset, const void* data,
|
||||
uint32_t num_dwords, uint8_t increment,
|
||||
uint8_t write_confirm);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbWriteDataGetSize(uint32_t num_dwords);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbGetLodStats(CommandBuffer* buf, uint8_t cache_policy,
|
||||
const volatile void* buffer,
|
||||
uint32_t buffer_size_in_bytes, uint32_t reset_count,
|
||||
uint8_t force_reset, uint8_t report_and_reset,
|
||||
uint32_t reporting_interval_in_100k_clocks);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbWaitRegMem(CommandBuffer* buf, uint8_t size,
|
||||
uint8_t compare_function, uint8_t op,
|
||||
uint8_t cache_policy, const volatile void* address,
|
||||
uint64_t reference, uint64_t mask,
|
||||
uint32_t poll_cycles);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDcbWaitOnAddressGetSize(uint32_t size);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetMarker(CommandBuffer* buf, const char* str, uint32_t color);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbPushMarker(CommandBuffer* buf, const char* str, uint32_t color);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbPopMarker(CommandBuffer* buf);
|
||||
|
||||
int KYTY_SYSV_ABI GraphicsWaitRegMemPatchAddress(uint32_t* cmd, const volatile void* address);
|
||||
int KYTY_SYSV_ABI GraphicsWaitRegMemPatchReference(uint32_t* cmd, uint64_t reference);
|
||||
int KYTY_SYSV_ABI GraphicsQueueEndOfPipeActionPatchAddress(uint32_t* cmd,
|
||||
const volatile Label* address);
|
||||
int KYTY_SYSV_ABI GraphicsQueueEndOfPipeActionPatchData(uint32_t* cmd, uint32_t context_id,
|
||||
uint32_t data_sel, uint64_t data);
|
||||
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbSetFlip(CommandBuffer* buf, uint32_t video_out_handle,
|
||||
int32_t display_buffer_index, uint32_t flip_mode,
|
||||
int64_t flip_arg);
|
||||
|
||||
} // namespace Gen5
|
||||
|
||||
namespace Gen5Driver {
|
||||
|
||||
struct Packet;
|
||||
|
||||
int KYTY_SYSV_ABI GraphicsDriverSubmitDcb(const Packet* packet);
|
||||
int KYTY_SYSV_ABI GraphicsDriverSubmitMultiDcbs(uint32_t* const* dcb_gpu_addrs,
|
||||
const uint32_t* dcb_sizes_in_dwords,
|
||||
uint32_t count);
|
||||
int KYTY_SYSV_ABI GraphicsDriverSubmitCommandBuffer(uint32_t queue, uint32_t* dcb,
|
||||
uint32_t size_in_dwords);
|
||||
int KYTY_SYSV_ABI GraphicsDriverSubmitMultiCommandBuffers(uint32_t queue, uint32_t* const* dcbs,
|
||||
const uint32_t* sizes_in_dwords,
|
||||
uint32_t count);
|
||||
int KYTY_SYSV_ABI GraphicsDriverSubmitAcb(uint32_t queue, const Packet* packet);
|
||||
int KYTY_SYSV_ABI GraphicsDriverSubmitMultiAcbs(uint32_t queue, uint32_t* const* acbs,
|
||||
const uint32_t* sizes_in_dwords, uint32_t count);
|
||||
int KYTY_SYSV_ABI GraphicsDriverAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id,
|
||||
void* udata);
|
||||
int KYTY_SYSV_ABI GraphicsDriverDeleteEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id);
|
||||
int KYTY_SYSV_ABI GraphicsDriverGetEqEventType(const LibKernel::EventQueue::KernelEvent* ev);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDriverGetEqContextId(const LibKernel::EventQueue::KernelEvent* ev);
|
||||
int KYTY_SYSV_ABI GraphicsDriverSetTFRing(const volatile void* base, uint32_t size);
|
||||
int KYTY_SYSV_ABI GraphicsDriverSetHsOffchipParam(uint64_t value0, uint64_t value1,
|
||||
uint64_t value2);
|
||||
bool KYTY_SYSV_ABI GraphicsDriverIsCaptureInProgress();
|
||||
int KYTY_SYSV_ABI GraphicsDriverUnknownU9ueyEhSkF4();
|
||||
|
||||
} // namespace Gen5Driver
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_AGC_H_ */
|
||||
File diff suppressed because it is too large.
Load diff
+1361
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,363 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/ajm/ffmpeg_decoder_common.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
namespace Libs::Audio::Ajm {
|
||||
|
||||
struct AjmDecM4aacInitializeParameters {
|
||||
uint32_t config_number;
|
||||
uint32_t sampling_freq_index;
|
||||
};
|
||||
|
||||
struct AjmSidebandDecM4aacCodecInfo {
|
||||
uint32_t heaac;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
static_assert(sizeof(AjmDecM4aacInitializeParameters) == 8);
|
||||
static_assert(sizeof(AjmSidebandDecM4aacCodecInfo) == 8);
|
||||
|
||||
static constexpr uint64_t AJM_INSTANCE_FLAG_DEC_M4AAC_ENABLE_SBR_DECODE =
|
||||
1ull << (AJM_INSTANCE_FLAG_CODEC_OFFSET + 0u);
|
||||
static constexpr uint64_t AJM_INSTANCE_FLAG_DEC_M4AAC_ENABLE_NONDELAY_OUTPUT =
|
||||
1ull << (AJM_INSTANCE_FLAG_CODEC_OFFSET + 1u);
|
||||
static constexpr uint32_t AJM_DEC_M4AAC_CONFIG_NUMBER_ADTS = 1;
|
||||
static constexpr uint32_t AJM_DEC_M4AAC_CONFIG_NUMBER_RAW = 2;
|
||||
static constexpr uint32_t AJM_DEC_M4AAC_CONFIG_NUMBER_SAF = 3;
|
||||
static constexpr uint32_t AJM_DEC_M4AAC_MAX_CHANNELS = 8;
|
||||
static constexpr uint32_t AJM_DEC_M4AAC_MAX_SAMPLING_FREQ_INDEX = 11;
|
||||
|
||||
class AjmAacDecoder final: public AjmDecoder {
|
||||
public:
|
||||
AjmAacDecoder(uint32_t channels, uint32_t sample_rate, AjmSampleEncoding encoding,
|
||||
uint64_t flags)
|
||||
: AjmDecoder(channels, sample_rate, encoding), m_flags(flags) {
|
||||
m_codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
|
||||
if (m_codec == nullptr) {
|
||||
LOGF("AJM AAC: avcodec_find_decoder failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
~AjmAacDecoder() override { Release(); }
|
||||
|
||||
AjmDecodeResult Initialize(const void* codec_parameters,
|
||||
size_t codec_parameters_size) override {
|
||||
auto result = MakeResult();
|
||||
|
||||
if (codec_parameters == nullptr ||
|
||||
codec_parameters_size < sizeof(AjmDecM4aacInitializeParameters)) {
|
||||
result.result = AJM_RESULT_INVALID_PARAMETER;
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto* params = static_cast<const AjmDecM4aacInitializeParameters*>(codec_parameters);
|
||||
if (params->config_number != AJM_DEC_M4AAC_CONFIG_NUMBER_ADTS &&
|
||||
params->config_number != AJM_DEC_M4AAC_CONFIG_NUMBER_RAW &&
|
||||
params->config_number != AJM_DEC_M4AAC_CONFIG_NUMBER_SAF) {
|
||||
result.result = AJM_RESULT_INVALID_PARAMETER;
|
||||
return result;
|
||||
}
|
||||
if (params->config_number == AJM_DEC_M4AAC_CONFIG_NUMBER_RAW &&
|
||||
params->sampling_freq_index > AJM_DEC_M4AAC_MAX_SAMPLING_FREQ_INDEX) {
|
||||
result.result = AJM_RESULT_INVALID_PARAMETER;
|
||||
return result;
|
||||
}
|
||||
|
||||
m_config_number = params->config_number;
|
||||
m_sampling_freq_index = params->sampling_freq_index;
|
||||
m_is_initialized = true;
|
||||
Reset();
|
||||
if (m_codec_context == nullptr) {
|
||||
m_is_initialized = false;
|
||||
result.result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return result;
|
||||
}
|
||||
|
||||
LOGF("AJM AAC initialized: config=%" PRIu32 ", freq_index=%" PRIu32 "\n", m_config_number,
|
||||
m_sampling_freq_index);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Reset() override {
|
||||
Release();
|
||||
m_skip_frames =
|
||||
((m_flags & AJM_INSTANCE_FLAG_DEC_M4AAC_ENABLE_NONDELAY_OUTPUT) != 0 ? 0u : 2u);
|
||||
m_total_decoded_samples = 0;
|
||||
m_bitrate = 0;
|
||||
if (m_is_initialized) {
|
||||
OpenDecoder();
|
||||
}
|
||||
}
|
||||
|
||||
AjmDecodeResult Decode(const void* input, size_t input_size, void* output, size_t output_size,
|
||||
bool multiple_frames, AjmGaplessState* gapless) override {
|
||||
(void)multiple_frames;
|
||||
auto result = MakeResult();
|
||||
|
||||
if (!m_is_initialized) {
|
||||
result.result = AJM_RESULT_NOT_INITIALIZED;
|
||||
return result;
|
||||
}
|
||||
if (m_codec_context == nullptr) {
|
||||
result.result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return result;
|
||||
}
|
||||
if (input == nullptr || input_size == 0) {
|
||||
result.result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return result;
|
||||
}
|
||||
if (input_size > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
result.result = AJM_RESULT_INVALID_PARAMETER;
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t output_offset = 0;
|
||||
if (!DecodePacket(static_cast<const uint8_t*>(input), static_cast<int>(input_size), output,
|
||||
output_size, &output_offset, gapless, &result)) {
|
||||
result.input_consumed = input_size;
|
||||
result.output_written = output_offset;
|
||||
result.total_decoded_samples = m_total_decoded_samples;
|
||||
result.format = GetFormat();
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result.frames == 0 && result.result == OK) {
|
||||
result.result = AJM_RESULT_PARTIAL_INPUT;
|
||||
}
|
||||
|
||||
result.input_consumed = input_size;
|
||||
result.output_written = output_offset;
|
||||
result.total_decoded_samples = m_total_decoded_samples;
|
||||
result.format = GetFormat();
|
||||
return result;
|
||||
}
|
||||
|
||||
void WriteCodecInfo(void* output, size_t output_size,
|
||||
const AjmDecodeResult& result) const override {
|
||||
(void)result;
|
||||
if (output == nullptr || output_size < sizeof(AjmSidebandDecM4aacCodecInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* info = static_cast<AjmSidebandDecM4aacCodecInfo*>(output);
|
||||
info->heaac = ((m_flags & AJM_INSTANCE_FLAG_DEC_M4AAC_ENABLE_SBR_DECODE) != 0 ? 1u : 0u);
|
||||
info->reserved = 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t CodecInfoSize() const override {
|
||||
return sizeof(AjmSidebandDecM4aacCodecInfo);
|
||||
}
|
||||
|
||||
[[nodiscard]] AjmSidebandFormat GetFormat() const override {
|
||||
auto format = AjmMakeFormat(m_channels, m_sample_rate, m_sample_encoding);
|
||||
format.bitrate = m_bitrate;
|
||||
return format;
|
||||
}
|
||||
|
||||
private:
|
||||
static uint32_t SamplingRateFromIndex(uint32_t index) {
|
||||
static constexpr uint32_t SAMPLE_RATES[] = {
|
||||
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000,
|
||||
};
|
||||
return (index < (sizeof(SAMPLE_RATES) / sizeof(SAMPLE_RATES[0])) ? SAMPLE_RATES[index]
|
||||
: 48000u);
|
||||
}
|
||||
|
||||
void Release() {
|
||||
if (m_codec_context != nullptr) {
|
||||
avcodec_free_context(&m_codec_context);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenDecoder() {
|
||||
if (m_codec == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_codec_context = avcodec_alloc_context3(m_codec);
|
||||
if (m_codec_context == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_config_number == AJM_DEC_M4AAC_CONFIG_NUMBER_RAW) {
|
||||
const auto sample_index =
|
||||
std::min(m_sampling_freq_index, AJM_DEC_M4AAC_MAX_SAMPLING_FREQ_INDEX);
|
||||
const auto channels = std::clamp<uint32_t>(m_channels, 1u, AJM_DEC_M4AAC_MAX_CHANNELS);
|
||||
constexpr uint32_t audio_object_type = 2;
|
||||
|
||||
auto* extradata = static_cast<uint8_t*>(av_mallocz(2 + AV_INPUT_BUFFER_PADDING_SIZE));
|
||||
if (extradata == nullptr) {
|
||||
Release();
|
||||
return;
|
||||
}
|
||||
|
||||
extradata[0] = static_cast<uint8_t>((audio_object_type << 3u) | (sample_index >> 1u));
|
||||
extradata[1] = static_cast<uint8_t>(((sample_index & 0x1u) << 7u) |
|
||||
(std::min(channels, 7u) << 3u));
|
||||
m_codec_context->extradata = extradata;
|
||||
m_codec_context->extradata_size = 2;
|
||||
SetFormat(channels, SamplingRateFromIndex(sample_index), m_sample_encoding);
|
||||
}
|
||||
|
||||
if (avcodec_open2(m_codec_context, m_codec, nullptr) < 0) {
|
||||
LOGF("AJM AAC: decoder initialization failed\n");
|
||||
Release();
|
||||
}
|
||||
}
|
||||
|
||||
bool WriteFrame(const AVFrame* frame, void* output, size_t output_size, size_t* output_offset,
|
||||
AjmGaplessState* gapless, AjmDecodeResult* result) {
|
||||
if (frame == nullptr || output_offset == nullptr || result == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto channels = static_cast<uint32_t>(std::max(frame->ch_layout.nb_channels, 1));
|
||||
const auto bpf = channels * AjmBytesPerSample(m_sample_encoding);
|
||||
if (bpf == 0) {
|
||||
result->result = AJM_RESULT_INVALID_PARAMETER;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetFormat(channels, static_cast<uint32_t>(std::max(frame->sample_rate, 1)),
|
||||
m_sample_encoding);
|
||||
if (m_codec_context != nullptr && m_codec_context->bit_rate > 0) {
|
||||
m_bitrate = static_cast<uint32_t>(m_codec_context->bit_rate);
|
||||
}
|
||||
|
||||
result->frames++;
|
||||
if (m_skip_frames > 0) {
|
||||
m_skip_frames--;
|
||||
result->format = GetFormat();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t skip_samples = 0;
|
||||
if (gapless != nullptr && gapless->current.skip_samples > 0) {
|
||||
skip_samples = std::min<uint32_t>(frame->nb_samples, gapless->current.skip_samples);
|
||||
gapless->current.skip_samples =
|
||||
static_cast<uint16_t>(gapless->current.skip_samples - skip_samples);
|
||||
}
|
||||
|
||||
uint32_t samples_to_write = static_cast<uint32_t>(frame->nb_samples) - skip_samples;
|
||||
if (gapless != nullptr && gapless->HasSampleLimit()) {
|
||||
samples_to_write = std::min(samples_to_write, gapless->current.total_samples);
|
||||
}
|
||||
|
||||
const auto requested_bytes = static_cast<size_t>(samples_to_write) * bpf;
|
||||
auto writable_bytes = requested_bytes;
|
||||
if (output == nullptr || *output_offset >= output_size) {
|
||||
writable_bytes = 0;
|
||||
} else {
|
||||
writable_bytes = std::min(writable_bytes, output_size - *output_offset);
|
||||
writable_bytes -= writable_bytes % bpf;
|
||||
}
|
||||
|
||||
if (writable_bytes != 0) {
|
||||
auto* dst = static_cast<uint8_t*>(output) + *output_offset;
|
||||
const auto* src = frame->data[0] + static_cast<size_t>(skip_samples) * bpf;
|
||||
std::memcpy(dst, src, writable_bytes);
|
||||
*output_offset += writable_bytes;
|
||||
}
|
||||
|
||||
const auto samples_written = static_cast<uint32_t>(writable_bytes / bpf);
|
||||
if (gapless != nullptr && gapless->HasSampleLimit()) {
|
||||
gapless->current.total_samples -=
|
||||
std::min(gapless->current.total_samples, samples_written);
|
||||
}
|
||||
if (gapless != nullptr) {
|
||||
const auto skipped_total =
|
||||
std::min<uint32_t>(std::numeric_limits<uint16_t>::max(),
|
||||
static_cast<uint32_t>(gapless->current.skipped_samples) +
|
||||
skip_samples + (samples_to_write - samples_written));
|
||||
gapless->current.skipped_samples = static_cast<uint16_t>(skipped_total);
|
||||
}
|
||||
|
||||
m_total_decoded_samples += samples_written;
|
||||
result->total_decoded_samples = m_total_decoded_samples;
|
||||
result->format = GetFormat();
|
||||
|
||||
if (writable_bytes != requested_bytes) {
|
||||
result->result |= AJM_RESULT_NOT_ENOUGH_ROOM;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodePacket(const uint8_t* packet_data, int packet_size, void* output, size_t output_size,
|
||||
size_t* output_offset, AjmGaplessState* gapless, AjmDecodeResult* result) {
|
||||
if (packet_data == nullptr || packet_size <= 0 || result == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
AVPacket* packet = av_packet_alloc();
|
||||
if (packet == nullptr || av_new_packet(packet, packet_size) < 0) {
|
||||
av_packet_free(&packet);
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return false;
|
||||
}
|
||||
std::memcpy(packet->data, packet_data, static_cast<size_t>(packet_size));
|
||||
|
||||
int rc = avcodec_send_packet(m_codec_context, packet);
|
||||
av_packet_free(&packet);
|
||||
if (rc == AVERROR_INVALIDDATA) {
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if (rc < 0) {
|
||||
result->result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
AVFrame* frame = av_frame_alloc();
|
||||
if (frame == nullptr) {
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = avcodec_receive_frame(m_codec_context, frame);
|
||||
if (rc == AVERROR(EAGAIN) || rc == AVERROR_EOF) {
|
||||
av_frame_free(&frame);
|
||||
return true;
|
||||
}
|
||||
if (rc < 0) {
|
||||
av_frame_free(&frame);
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
|
||||
AVFrame* converted = AjmConvertFfmpegFrame(frame, m_sample_encoding, result);
|
||||
av_frame_free(&frame);
|
||||
if (converted == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool ok =
|
||||
WriteFrame(converted, output, output_size, output_offset, gapless, result);
|
||||
av_frame_free(&converted);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AVCodec* m_codec = nullptr;
|
||||
AVCodecContext* m_codec_context = nullptr;
|
||||
uint64_t m_flags = 0;
|
||||
uint32_t m_config_number = AJM_DEC_M4AAC_CONFIG_NUMBER_ADTS;
|
||||
uint32_t m_sampling_freq_index = 3;
|
||||
uint32_t m_skip_frames = 2;
|
||||
uint32_t m_bitrate = 0;
|
||||
bool m_is_initialized = false;
|
||||
};
|
||||
|
||||
} // namespace Libs::Audio::Ajm
|
||||
@@ -0,0 +1,530 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
#include "libatrac9.h"
|
||||
}
|
||||
|
||||
namespace Libs::Audio::Ajm {
|
||||
|
||||
struct AjmDecAt9InitializeParameters {
|
||||
uint8_t config_data[ATRAC9_CONFIG_DATA_SIZE];
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
struct AjmSidebandDecAt9CodecInfo {
|
||||
uint32_t super_frame_size;
|
||||
uint32_t frames_in_super_frame;
|
||||
uint32_t next_frame_size;
|
||||
uint32_t frame_samples;
|
||||
};
|
||||
|
||||
static constexpr uint64_t AJM_INSTANCE_FLAG_DEC_AT9_PARSE_RIFF_HEADER =
|
||||
1ull << (AJM_INSTANCE_FLAG_CODEC_OFFSET + 0u);
|
||||
|
||||
static uint16_t AjmReadLe16(const uint8_t* data) {
|
||||
return static_cast<uint16_t>(data[0]) | (static_cast<uint16_t>(data[1]) << 8u);
|
||||
}
|
||||
|
||||
static uint32_t AjmReadLe32(const uint8_t* data) {
|
||||
return static_cast<uint32_t>(data[0]) | (static_cast<uint32_t>(data[1]) << 8u) |
|
||||
(static_cast<uint32_t>(data[2]) << 16u) | (static_cast<uint32_t>(data[3]) << 24u);
|
||||
}
|
||||
|
||||
static bool AjmFourCcEquals(const uint8_t* data, char a, char b, char c, char d) {
|
||||
return data[0] == static_cast<uint8_t>(a) && data[1] == static_cast<uint8_t>(b) &&
|
||||
data[2] == static_cast<uint8_t>(c) && data[3] == static_cast<uint8_t>(d);
|
||||
}
|
||||
|
||||
class AjmAt9Decoder final: public AjmDecoder {
|
||||
public:
|
||||
AjmAt9Decoder(uint32_t channels, uint32_t sample_rate, AjmSampleEncoding encoding,
|
||||
uint64_t flags)
|
||||
: AjmDecoder(channels, sample_rate, encoding),
|
||||
m_parse_riff_header((flags & AJM_INSTANCE_FLAG_DEC_AT9_PARSE_RIFF_HEADER) != 0),
|
||||
m_handle(Atrac9GetHandle()) {}
|
||||
|
||||
~AjmAt9Decoder() override {
|
||||
if (m_handle != nullptr) {
|
||||
Atrac9ReleaseHandle(m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
AjmDecodeResult Initialize(const void* codec_parameters,
|
||||
size_t codec_parameters_size) override {
|
||||
auto result = MakeResult();
|
||||
|
||||
if (codec_parameters == nullptr || codec_parameters_size < ATRAC9_CONFIG_DATA_SIZE) {
|
||||
result.result = AJM_RESULT_INVALID_PARAMETER;
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto* params = static_cast<const AjmDecAt9InitializeParameters*>(codec_parameters);
|
||||
if (!InitializeConfig(params->config_data, &result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return MakeResult();
|
||||
}
|
||||
|
||||
void Reset() override {
|
||||
if (m_handle != nullptr) {
|
||||
Atrac9ReleaseHandle(m_handle);
|
||||
}
|
||||
m_handle = Atrac9GetHandle();
|
||||
m_num_frames = 0;
|
||||
m_total_decoded_samples = 0;
|
||||
m_superframe_bytes_remain =
|
||||
(m_is_initialized ? static_cast<uint32_t>(m_codec_info.superframeSize) : 0);
|
||||
|
||||
if (m_has_config && m_handle != nullptr) {
|
||||
auto result = MakeResult();
|
||||
(void)InitializeConfig(m_config_data, &result);
|
||||
}
|
||||
}
|
||||
|
||||
AjmDecodeResult Decode(const void* input, size_t input_size, void* output, size_t output_size,
|
||||
bool multiple_frames, AjmGaplessState* gapless) override {
|
||||
auto result = MakeResult();
|
||||
|
||||
if (input == nullptr || input_size == 0) {
|
||||
result.result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto* input_bytes = static_cast<const uint8_t*>(input);
|
||||
auto* output_bytes = static_cast<uint8_t*>(output);
|
||||
size_t input_offset = 0;
|
||||
|
||||
if (m_parse_riff_header && input_size >= 12 &&
|
||||
AjmFourCcEquals(input_bytes, 'R', 'I', 'F', 'F')) {
|
||||
if (!ParseRiffHeader(input_bytes, input_size, &input_offset, gapless, &result)) {
|
||||
return result;
|
||||
}
|
||||
if (input_offset >= input_size) {
|
||||
result.input_consumed = input_offset;
|
||||
result.result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_is_initialized) {
|
||||
result.result = AJM_RESULT_NOT_INITIALIZED;
|
||||
return result;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (input_offset >= input_size) {
|
||||
break;
|
||||
}
|
||||
if (gapless != nullptr && gapless->IsEnd()) {
|
||||
break;
|
||||
}
|
||||
|
||||
const auto remaining_input = input_size - input_offset;
|
||||
if (remaining_input < GetMinimumInputSize()) {
|
||||
if (result.frames == 0) {
|
||||
result.result = AJM_RESULT_PARTIAL_INPUT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const auto frame_output_bytes = FrameOutputBytes(gapless);
|
||||
if (frame_output_bytes != 0 && output == nullptr) {
|
||||
result.result |= AJM_RESULT_NOT_ENOUGH_ROOM;
|
||||
break;
|
||||
}
|
||||
if (frame_output_bytes == 0 && !FrameCanProduceNoOutput(gapless)) {
|
||||
result.result |= AJM_RESULT_NOT_ENOUGH_ROOM;
|
||||
break;
|
||||
}
|
||||
if (output_size - result.output_written < frame_output_bytes) {
|
||||
result.result |= AJM_RESULT_NOT_ENOUGH_ROOM;
|
||||
break;
|
||||
}
|
||||
|
||||
int bytes_used = 0;
|
||||
const int ret = DecodeFrame(input_bytes + input_offset, &bytes_used);
|
||||
if (ret != 0) {
|
||||
result.result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
result.internal_result = ret;
|
||||
break;
|
||||
}
|
||||
if (bytes_used <= 0 || static_cast<size_t>(bytes_used) > remaining_input ||
|
||||
static_cast<uint32_t>(bytes_used) > m_superframe_bytes_remain) {
|
||||
result.result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto samples_written =
|
||||
CopyDecodedFrame(output_bytes, output_size, &result.output_written, gapless);
|
||||
|
||||
input_offset += static_cast<size_t>(bytes_used);
|
||||
result.input_consumed = input_offset;
|
||||
result.frames++;
|
||||
m_total_decoded_samples += samples_written;
|
||||
|
||||
AdvanceSuperframe(static_cast<uint32_t>(bytes_used), input_size, &input_offset,
|
||||
&result);
|
||||
if (gapless != nullptr && gapless->IsEnd()) {
|
||||
DrainSuperframe(input_bytes, input_size, &input_offset, &result);
|
||||
}
|
||||
if (result.result != OK || !multiple_frames) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.total_decoded_samples = m_total_decoded_samples;
|
||||
result.format = GetFormat();
|
||||
return result;
|
||||
}
|
||||
|
||||
void WriteCodecInfo(void* output, size_t output_size,
|
||||
const AjmDecodeResult& result) const override {
|
||||
(void)result;
|
||||
if (output == nullptr || output_size < sizeof(AjmSidebandDecAt9CodecInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* info = static_cast<AjmSidebandDecAt9CodecInfo*>(output);
|
||||
info->super_frame_size =
|
||||
m_is_initialized ? static_cast<uint32_t>(m_codec_info.superframeSize) : 0;
|
||||
info->frames_in_super_frame =
|
||||
m_is_initialized ? static_cast<uint32_t>(m_codec_info.framesInSuperframe) : 0;
|
||||
info->next_frame_size = GetMinimumInputSize();
|
||||
info->frame_samples =
|
||||
m_is_initialized ? static_cast<uint32_t>(m_codec_info.frameSamples) : 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t CodecInfoSize() const override {
|
||||
return sizeof(AjmSidebandDecAt9CodecInfo);
|
||||
}
|
||||
|
||||
[[nodiscard]] AjmSidebandFormat GetFormat() const override {
|
||||
auto format = AjmMakeFormat(
|
||||
m_is_initialized ? static_cast<uint32_t>(m_codec_info.channels) : m_channels,
|
||||
m_is_initialized ? static_cast<uint32_t>(m_codec_info.samplingRate) : m_sample_rate,
|
||||
m_sample_encoding);
|
||||
if (m_is_initialized && m_codec_info.framesInSuperframe > 0 &&
|
||||
m_codec_info.frameSamples > 0) {
|
||||
format.bitrate =
|
||||
static_cast<uint32_t>((static_cast<uint64_t>(m_codec_info.samplingRate) *
|
||||
static_cast<uint64_t>(m_codec_info.superframeSize) * 8u) /
|
||||
(static_cast<uint64_t>(m_codec_info.framesInSuperframe) *
|
||||
static_cast<uint64_t>(m_codec_info.frameSamples)));
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] uint32_t FrameOutputSamples(const AjmGaplessState* gapless) const {
|
||||
if (!m_is_initialized || m_codec_info.channels <= 0 || m_codec_info.frameSamples <= 0) {
|
||||
return 0;
|
||||
}
|
||||
auto samples = static_cast<uint32_t>(m_codec_info.frameSamples);
|
||||
if (gapless != nullptr) {
|
||||
const auto skip_samples = std::min<uint32_t>(samples, gapless->current.skip_samples);
|
||||
samples -= skip_samples;
|
||||
if (gapless->HasSampleLimit()) {
|
||||
samples = std::min<uint32_t>(samples, gapless->current.total_samples);
|
||||
}
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool FrameCanProduceNoOutput(const AjmGaplessState* gapless) const {
|
||||
return m_is_initialized && m_codec_info.channels > 0 && m_codec_info.frameSamples > 0 &&
|
||||
gapless != nullptr &&
|
||||
(gapless->current.skip_samples != 0 ||
|
||||
(gapless->HasSampleLimit() && gapless->current.total_samples == 0));
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t FrameOutputBytes(const AjmGaplessState* gapless = nullptr) const {
|
||||
if (!m_is_initialized || m_codec_info.channels <= 0 || m_codec_info.frameSamples <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<size_t>(m_codec_info.channels) *
|
||||
static_cast<size_t>(FrameOutputSamples(gapless)) *
|
||||
AjmBytesPerSample(m_sample_encoding);
|
||||
}
|
||||
|
||||
[[nodiscard]] uint32_t GetMinimumInputSize() const {
|
||||
return (m_is_initialized ? m_superframe_bytes_remain : 0);
|
||||
}
|
||||
|
||||
bool InitializeConfig(const uint8_t* config_data, AjmDecodeResult* result) {
|
||||
if (config_data == nullptr || result == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (m_handle == nullptr) {
|
||||
m_handle = Atrac9GetHandle();
|
||||
}
|
||||
if (m_handle == nullptr) {
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memcpy(m_config_data, config_data, ATRAC9_CONFIG_DATA_SIZE);
|
||||
m_has_config = true;
|
||||
|
||||
const int init_ret = Atrac9InitDecoder(m_handle, m_config_data);
|
||||
if (init_ret != 0) {
|
||||
m_is_initialized = false;
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
result->internal_result = init_ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
const int info_ret = Atrac9GetCodecInfo(m_handle, &m_codec_info);
|
||||
if (info_ret != 0 || m_codec_info.channels <= 0 || m_codec_info.frameSamples <= 0 ||
|
||||
m_codec_info.superframeSize <= 0 || m_codec_info.framesInSuperframe <= 0) {
|
||||
m_is_initialized = false;
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
result->internal_result = info_ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_is_initialized = true;
|
||||
m_num_frames = 0;
|
||||
m_total_decoded_samples = 0;
|
||||
m_superframe_bytes_remain = static_cast<uint32_t>(m_codec_info.superframeSize);
|
||||
SetFormat(static_cast<uint32_t>(m_codec_info.channels),
|
||||
static_cast<uint32_t>(m_codec_info.samplingRate), m_sample_encoding);
|
||||
m_pcm_buffer.assign(FrameOutputBytes(), 0);
|
||||
|
||||
LOGF("AJM ATRAC9 initialized: %d Hz, %d ch, frame_samples=%d, superframe=%d bytes/%d "
|
||||
"frames\n",
|
||||
m_codec_info.samplingRate, m_codec_info.channels, m_codec_info.frameSamples,
|
||||
m_codec_info.superframeSize, m_codec_info.framesInSuperframe);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int DecodeFrame(const uint8_t* input, int* bytes_used) {
|
||||
switch (m_sample_encoding) {
|
||||
case AjmSampleEncoding::S16:
|
||||
return Atrac9Decode(m_handle, input,
|
||||
reinterpret_cast<int16_t*>(m_pcm_buffer.data()), bytes_used, 0);
|
||||
case AjmSampleEncoding::S32:
|
||||
return Atrac9DecodeS32(m_handle, input,
|
||||
reinterpret_cast<int32_t*>(m_pcm_buffer.data()), bytes_used,
|
||||
0);
|
||||
case AjmSampleEncoding::Float:
|
||||
return Atrac9DecodeF32(
|
||||
m_handle, input, reinterpret_cast<float*>(m_pcm_buffer.data()), bytes_used, 0);
|
||||
default:
|
||||
EXIT("unsupported AJM PCM sample encoding %u\n",
|
||||
static_cast<uint32_t>(m_sample_encoding));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t CopyDecodedFrame(uint8_t* output, size_t output_size, size_t* output_written,
|
||||
AjmGaplessState* gapless) {
|
||||
EXIT_IF(output_written == nullptr);
|
||||
if (!m_is_initialized || m_codec_info.channels <= 0 || m_codec_info.frameSamples <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto channels = static_cast<uint32_t>(m_codec_info.channels);
|
||||
const auto frame_samples = static_cast<uint32_t>(m_codec_info.frameSamples);
|
||||
const auto bytes_per_frame =
|
||||
static_cast<size_t>(channels) * AjmBytesPerSample(m_sample_encoding);
|
||||
auto skip_samples = 0u;
|
||||
auto samples_to_write = frame_samples;
|
||||
|
||||
if (gapless != nullptr) {
|
||||
skip_samples = std::min<uint32_t>(frame_samples, gapless->current.skip_samples);
|
||||
gapless->current.skip_samples =
|
||||
static_cast<uint16_t>(gapless->current.skip_samples - skip_samples);
|
||||
|
||||
samples_to_write -= skip_samples;
|
||||
if (gapless->HasSampleLimit()) {
|
||||
samples_to_write =
|
||||
std::min<uint32_t>(samples_to_write, gapless->current.total_samples);
|
||||
}
|
||||
}
|
||||
|
||||
const auto copy_bytes = static_cast<size_t>(samples_to_write) * bytes_per_frame;
|
||||
if (copy_bytes != 0) {
|
||||
EXIT_IF(output == nullptr);
|
||||
EXIT_IF(*output_written > output_size || copy_bytes > output_size - *output_written);
|
||||
std::memcpy(output + *output_written,
|
||||
m_pcm_buffer.data() + static_cast<size_t>(skip_samples) * bytes_per_frame,
|
||||
copy_bytes);
|
||||
*output_written += copy_bytes;
|
||||
}
|
||||
|
||||
if (gapless != nullptr) {
|
||||
if (gapless->HasSampleLimit()) {
|
||||
gapless->current.total_samples =
|
||||
(gapless->current.total_samples > samples_to_write
|
||||
? gapless->current.total_samples - samples_to_write
|
||||
: 0);
|
||||
}
|
||||
|
||||
const auto skipped_samples = frame_samples - samples_to_write;
|
||||
const auto skipped_total = std::min<uint32_t>(
|
||||
std::numeric_limits<uint16_t>::max(),
|
||||
static_cast<uint32_t>(gapless->current.skipped_samples) + skipped_samples);
|
||||
gapless->current.skipped_samples = static_cast<uint16_t>(skipped_total);
|
||||
}
|
||||
|
||||
return samples_to_write;
|
||||
}
|
||||
|
||||
void AdvanceSuperframe(uint32_t bytes_used, size_t input_size, size_t* input_offset,
|
||||
AjmDecodeResult* result) {
|
||||
EXIT_IF(input_offset == nullptr);
|
||||
EXIT_IF(result == nullptr);
|
||||
|
||||
m_superframe_bytes_remain -= bytes_used;
|
||||
m_num_frames++;
|
||||
|
||||
if (m_num_frames < static_cast<uint32_t>(m_codec_info.framesInSuperframe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_superframe_bytes_remain != 0) {
|
||||
const auto remaining_input =
|
||||
(*input_offset < input_size ? input_size - *input_offset : 0);
|
||||
if (remaining_input < m_superframe_bytes_remain) {
|
||||
result->result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return;
|
||||
}
|
||||
*input_offset += m_superframe_bytes_remain;
|
||||
result->input_consumed = *input_offset;
|
||||
}
|
||||
|
||||
m_superframe_bytes_remain = static_cast<uint32_t>(m_codec_info.superframeSize);
|
||||
m_num_frames = 0;
|
||||
}
|
||||
|
||||
void DrainSuperframe(const uint8_t* input, size_t input_size, size_t* input_offset,
|
||||
AjmDecodeResult* result) {
|
||||
EXIT_IF(input_offset == nullptr);
|
||||
EXIT_IF(result == nullptr);
|
||||
|
||||
while (m_num_frames != 0) {
|
||||
const auto remaining_input =
|
||||
(*input_offset < input_size ? input_size - *input_offset : 0);
|
||||
if (remaining_input < GetMinimumInputSize()) {
|
||||
result->result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return;
|
||||
}
|
||||
|
||||
int bytes_used = 0;
|
||||
const int ret = DecodeFrame(input + *input_offset, &bytes_used);
|
||||
if (ret != 0) {
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
result->internal_result = ret;
|
||||
return;
|
||||
}
|
||||
if (bytes_used <= 0 || static_cast<size_t>(bytes_used) > remaining_input ||
|
||||
static_cast<uint32_t>(bytes_used) > m_superframe_bytes_remain) {
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
*input_offset += static_cast<size_t>(bytes_used);
|
||||
result->input_consumed = *input_offset;
|
||||
result->frames++;
|
||||
AdvanceSuperframe(static_cast<uint32_t>(bytes_used), input_size, input_offset, result);
|
||||
if (result->result != OK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ParseRiffHeader(const uint8_t* input, size_t input_size, size_t* data_offset,
|
||||
AjmGaplessState* gapless, AjmDecodeResult* result) {
|
||||
EXIT_IF(data_offset == nullptr);
|
||||
EXIT_IF(result == nullptr);
|
||||
|
||||
*data_offset = 0;
|
||||
if (input_size < 12 || !AjmFourCcEquals(input, 'R', 'I', 'F', 'F') ||
|
||||
!AjmFourCcEquals(input + 8, 'W', 'A', 'V', 'E')) {
|
||||
result->result = AJM_RESULT_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t offset = 12;
|
||||
while (offset + 8 <= input_size) {
|
||||
const auto* chunk = input + offset;
|
||||
const auto chunk_size = static_cast<size_t>(AjmReadLe32(chunk + 4));
|
||||
const auto payload = offset + 8;
|
||||
if (payload > input_size || chunk_size > input_size - payload) {
|
||||
result->result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AjmFourCcEquals(chunk, 'f', 'm', 't', ' ')) {
|
||||
if (chunk_size < 48) {
|
||||
result->result = AJM_RESULT_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
const auto* fmt = input + payload;
|
||||
static constexpr uint8_t AT9_GUID[16] = {0xd2, 0x42, 0xe1, 0x47, 0xba, 0x36,
|
||||
0x8d, 0x4d, 0x88, 0xfc, 0x61, 0x65,
|
||||
0x4f, 0x8c, 0x83, 0x6c};
|
||||
if (AjmReadLe16(fmt) != 0xfffe ||
|
||||
std::memcmp(fmt + 24, AT9_GUID, sizeof(AT9_GUID)) != 0) {
|
||||
result->result = AJM_RESULT_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
if (!InitializeConfig(fmt + 44, result)) {
|
||||
return false;
|
||||
}
|
||||
} else if (AjmFourCcEquals(chunk, 'f', 'a', 'c', 't')) {
|
||||
if (chunk_size >= 12 && gapless != nullptr) {
|
||||
AjmSidebandGaplessDecode gapless_decode {};
|
||||
gapless_decode.total_samples = AjmReadLe32(input + payload);
|
||||
gapless_decode.skip_samples = static_cast<uint16_t>(std::min<uint32_t>(
|
||||
AjmReadLe32(input + payload + 4), std::numeric_limits<uint16_t>::max()));
|
||||
gapless->Set(gapless_decode, true);
|
||||
LOGF("AJM ATRAC9 gapless: total=%" PRIu32 ", skip=%" PRIu16 "\n",
|
||||
gapless_decode.total_samples, gapless_decode.skip_samples);
|
||||
}
|
||||
} else if (AjmFourCcEquals(chunk, 'd', 'a', 't', 'a')) {
|
||||
*data_offset = payload;
|
||||
result->input_consumed = payload;
|
||||
result->format = GetFormat();
|
||||
result->total_decoded_samples = m_total_decoded_samples;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto padded_size = chunk_size + (chunk_size & 1u);
|
||||
if (padded_size > std::numeric_limits<size_t>::max() - 8 ||
|
||||
offset > std::numeric_limits<size_t>::max() - 8 - padded_size) {
|
||||
result->result = AJM_RESULT_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
offset += 8 + padded_size;
|
||||
}
|
||||
|
||||
result->result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool m_parse_riff_header = false;
|
||||
bool m_is_initialized = false;
|
||||
bool m_has_config = false;
|
||||
void* m_handle = nullptr;
|
||||
uint8_t m_config_data[ATRAC9_CONFIG_DATA_SIZE] {};
|
||||
uint32_t m_superframe_bytes_remain = 0;
|
||||
uint32_t m_num_frames = 0;
|
||||
Atrac9CodecInfo m_codec_info {};
|
||||
std::vector<uint8_t> m_pcm_buffer;
|
||||
};
|
||||
|
||||
} // namespace Libs::Audio::Ajm
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/assert.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/channel_layout.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/samplefmt.h>
|
||||
#include <libswresample/swresample.h>
|
||||
}
|
||||
|
||||
namespace Libs::Audio::Ajm {
|
||||
|
||||
static AVSampleFormat AjmSampleEncodingToAvFormat(AjmSampleEncoding encoding) {
|
||||
switch (encoding) {
|
||||
case AjmSampleEncoding::S16: return AV_SAMPLE_FMT_S16;
|
||||
case AjmSampleEncoding::S32: return AV_SAMPLE_FMT_S32;
|
||||
case AjmSampleEncoding::Float: return AV_SAMPLE_FMT_FLT;
|
||||
default: EXIT("unsupported AJM PCM sample encoding %u\n", static_cast<uint32_t>(encoding));
|
||||
}
|
||||
return AV_SAMPLE_FMT_S16;
|
||||
}
|
||||
|
||||
static AVFrame* AjmConvertFfmpegFrame(const AVFrame* frame, AjmSampleEncoding encoding,
|
||||
AjmDecodeResult* result) {
|
||||
if (frame == nullptr || result == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AVFrame* converted = av_frame_alloc();
|
||||
if (converted == nullptr) {
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
converted->format = AjmSampleEncodingToAvFormat(encoding);
|
||||
converted->sample_rate = frame->sample_rate;
|
||||
converted->nb_samples = frame->nb_samples;
|
||||
if (av_channel_layout_copy(&converted->ch_layout, &frame->ch_layout) < 0 ||
|
||||
av_frame_get_buffer(converted, 0) < 0) {
|
||||
av_frame_free(&converted);
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SwrContext* swr = nullptr;
|
||||
int swr_result = swr_alloc_set_opts2(
|
||||
&swr, &converted->ch_layout, static_cast<AVSampleFormat>(converted->format),
|
||||
converted->sample_rate, &frame->ch_layout, static_cast<AVSampleFormat>(frame->format),
|
||||
frame->sample_rate, 0, nullptr);
|
||||
if (swr_result < 0 || swr_init(swr) < 0 || swr_convert_frame(swr, converted, frame) < 0) {
|
||||
swr_free(&swr);
|
||||
av_frame_free(&converted);
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
return nullptr;
|
||||
}
|
||||
swr_free(&swr);
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
} // namespace Libs::Audio::Ajm
|
||||
@@ -0,0 +1,393 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/ajm/ffmpeg_decoder_common.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
namespace Libs::Audio::Ajm {
|
||||
|
||||
struct AjmSidebandDecMp3CodecInfo {
|
||||
uint32_t header;
|
||||
uint8_t crc;
|
||||
uint8_t mode;
|
||||
uint8_t mode_extension;
|
||||
uint8_t copyright;
|
||||
uint8_t original;
|
||||
uint8_t emphasis;
|
||||
uint16_t reserved[3];
|
||||
};
|
||||
|
||||
static_assert(sizeof(AjmSidebandDecMp3CodecInfo) == 16);
|
||||
|
||||
struct AjmMp3FrameHeader {
|
||||
uint32_t header = 0;
|
||||
uint32_t frame_size = 0;
|
||||
uint32_t num_channels = 0;
|
||||
uint32_t samples_per_channel = 0;
|
||||
uint32_t bitrate = 0;
|
||||
uint32_t sample_rate = 0;
|
||||
uint8_t crc = 0;
|
||||
uint8_t mode = 0;
|
||||
uint8_t mode_extension = 0;
|
||||
uint8_t copyright = 0;
|
||||
uint8_t original = 0;
|
||||
uint8_t emphasis = 0;
|
||||
};
|
||||
|
||||
static uint32_t AjmReadBe32(const uint8_t* data) {
|
||||
return (static_cast<uint32_t>(data[0]) << 24u) | (static_cast<uint32_t>(data[1]) << 16u) |
|
||||
(static_cast<uint32_t>(data[2]) << 8u) | static_cast<uint32_t>(data[3]);
|
||||
}
|
||||
|
||||
static bool AjmParseMp3Header(const uint8_t* data, size_t size, AjmMp3FrameHeader* out) {
|
||||
if (data == nullptr || size < 4 || out == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t header = AjmReadBe32(data);
|
||||
if ((header & 0xffe00000u) != 0xffe00000u) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto version_id = (header >> 19u) & 0x3u;
|
||||
const auto layer_id = (header >> 17u) & 0x3u;
|
||||
const auto protection_bit = (header >> 16u) & 0x1u;
|
||||
const auto bitrate_index = (header >> 12u) & 0xfu;
|
||||
const auto sample_index = (header >> 10u) & 0x3u;
|
||||
const auto padding = (header >> 9u) & 0x1u;
|
||||
const auto channel_mode = (header >> 6u) & 0x3u;
|
||||
const auto mode_extension = (header >> 4u) & 0x3u;
|
||||
const auto copyright = (header >> 3u) & 0x1u;
|
||||
const auto original = (header >> 2u) & 0x1u;
|
||||
const auto emphasis = header & 0x3u;
|
||||
|
||||
if (version_id == 1 || layer_id != 1 || sample_index == 3 || bitrate_index == 0 ||
|
||||
bitrate_index == 15) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr uint32_t SAMPLE_RATES[4][3] = {
|
||||
{11025, 12000, 8000},
|
||||
{0, 0, 0},
|
||||
{22050, 24000, 16000},
|
||||
{44100, 48000, 32000},
|
||||
};
|
||||
static constexpr uint32_t BITRATES_MPEG1[16] = {
|
||||
0, 32000, 40000, 48000, 56000, 64000, 80000, 96000,
|
||||
112000, 128000, 160000, 192000, 224000, 256000, 320000, 0,
|
||||
};
|
||||
static constexpr uint32_t BITRATES_MPEG2[16] = {
|
||||
0, 8000, 16000, 24000, 32000, 40000, 48000, 56000,
|
||||
64000, 80000, 96000, 112000, 128000, 144000, 160000, 0,
|
||||
};
|
||||
|
||||
const auto sample_rate = SAMPLE_RATES[version_id][sample_index];
|
||||
const auto bitrate =
|
||||
(version_id == 3 ? BITRATES_MPEG1[bitrate_index] : BITRATES_MPEG2[bitrate_index]);
|
||||
if (sample_rate == 0 || bitrate == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool mpeg1 = (version_id == 3);
|
||||
|
||||
out->header = header;
|
||||
out->frame_size =
|
||||
(mpeg1 ? (144u * bitrate) / sample_rate : (72u * bitrate) / sample_rate) + padding;
|
||||
out->num_channels = (channel_mode == 3 ? 1u : 2u);
|
||||
out->samples_per_channel = (mpeg1 ? 1152u : 576u);
|
||||
out->bitrate = bitrate;
|
||||
out->sample_rate = sample_rate;
|
||||
out->crc = static_cast<uint8_t>(protection_bit);
|
||||
out->mode = static_cast<uint8_t>(channel_mode);
|
||||
out->mode_extension = static_cast<uint8_t>(mode_extension);
|
||||
out->copyright = static_cast<uint8_t>(copyright);
|
||||
out->original = static_cast<uint8_t>(original);
|
||||
out->emphasis = static_cast<uint8_t>(emphasis);
|
||||
return true;
|
||||
}
|
||||
|
||||
class AjmMp3Decoder final: public AjmDecoder {
|
||||
public:
|
||||
AjmMp3Decoder(uint32_t channels, uint32_t sample_rate, AjmSampleEncoding encoding,
|
||||
uint64_t flags)
|
||||
: AjmDecoder(channels, sample_rate, encoding) {
|
||||
(void)flags;
|
||||
|
||||
m_codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
|
||||
if (m_codec == nullptr) {
|
||||
LOGF("AJM MP3: avcodec_find_decoder failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
m_codec_context = avcodec_alloc_context3(m_codec);
|
||||
m_parser = av_parser_init(m_codec->id);
|
||||
if (m_codec_context == nullptr || m_parser == nullptr ||
|
||||
avcodec_open2(m_codec_context, m_codec, nullptr) < 0) {
|
||||
LOGF("AJM MP3: decoder initialization failed\n");
|
||||
Release();
|
||||
}
|
||||
}
|
||||
|
||||
~AjmMp3Decoder() override { Release(); }
|
||||
|
||||
void Reset() override {
|
||||
if (m_codec_context != nullptr) {
|
||||
avcodec_flush_buffers(m_codec_context);
|
||||
}
|
||||
if (m_parser != nullptr) {
|
||||
av_parser_close(m_parser);
|
||||
m_parser = (m_codec != nullptr ? av_parser_init(m_codec->id) : nullptr);
|
||||
}
|
||||
m_total_decoded_samples = 0;
|
||||
m_have_header = false;
|
||||
m_bitrate = 0;
|
||||
}
|
||||
|
||||
AjmDecodeResult Decode(const void* input, size_t input_size, void* output, size_t output_size,
|
||||
bool multiple_frames, AjmGaplessState* gapless) override {
|
||||
auto result = MakeResult();
|
||||
|
||||
if (m_codec_context == nullptr || m_parser == nullptr) {
|
||||
result.result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return result;
|
||||
}
|
||||
if (input == nullptr || input_size == 0) {
|
||||
result.result = AJM_RESULT_PARTIAL_INPUT;
|
||||
return result;
|
||||
}
|
||||
if (input_size > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
result.result = AJM_RESULT_INVALID_PARAMETER;
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto* input_bytes = static_cast<const uint8_t*>(input);
|
||||
size_t input_offset = 0;
|
||||
size_t output_offset = 0;
|
||||
bool decoded = false;
|
||||
|
||||
while (input_offset < input_size) {
|
||||
AjmMp3FrameHeader header {};
|
||||
if (AjmParseMp3Header(input_bytes + input_offset, input_size - input_offset, &header)) {
|
||||
m_last_header = header;
|
||||
m_have_header = true;
|
||||
}
|
||||
|
||||
uint8_t* packet_data = nullptr;
|
||||
int packet_size = 0;
|
||||
const int consumed = av_parser_parse2(
|
||||
m_parser, m_codec_context, &packet_data, &packet_size, input_bytes + input_offset,
|
||||
static_cast<int>(input_size - input_offset), AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
|
||||
if (consumed < 0) {
|
||||
result.result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
input_offset += static_cast<size_t>(consumed);
|
||||
if (packet_size > 0) {
|
||||
if (!DecodePacket(packet_data, packet_size, output, output_size, &output_offset,
|
||||
gapless, &result)) {
|
||||
break;
|
||||
}
|
||||
decoded = true;
|
||||
if (!multiple_frames) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (consumed == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!decoded && result.result == OK) {
|
||||
result.result = AJM_RESULT_PARTIAL_INPUT;
|
||||
}
|
||||
|
||||
result.input_consumed = input_offset;
|
||||
result.output_written = output_offset;
|
||||
result.total_decoded_samples = m_total_decoded_samples;
|
||||
result.format = GetFormat();
|
||||
return result;
|
||||
}
|
||||
|
||||
void WriteCodecInfo(void* output, size_t output_size,
|
||||
const AjmDecodeResult& result) const override {
|
||||
(void)result;
|
||||
if (output == nullptr || output_size < sizeof(AjmSidebandDecMp3CodecInfo) ||
|
||||
!m_have_header) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* info = static_cast<AjmSidebandDecMp3CodecInfo*>(output);
|
||||
info->header = m_last_header.header;
|
||||
info->crc = m_last_header.crc;
|
||||
info->mode = m_last_header.mode;
|
||||
info->mode_extension = m_last_header.mode_extension;
|
||||
info->copyright = m_last_header.copyright;
|
||||
info->original = m_last_header.original;
|
||||
info->emphasis = m_last_header.emphasis;
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t CodecInfoSize() const override {
|
||||
return sizeof(AjmSidebandDecMp3CodecInfo);
|
||||
}
|
||||
|
||||
[[nodiscard]] AjmSidebandFormat GetFormat() const override {
|
||||
auto format = AjmMakeFormat(m_channels, m_sample_rate, m_sample_encoding);
|
||||
format.bitrate = m_bitrate;
|
||||
return format;
|
||||
}
|
||||
|
||||
private:
|
||||
void Release() {
|
||||
if (m_parser != nullptr) {
|
||||
av_parser_close(m_parser);
|
||||
m_parser = nullptr;
|
||||
}
|
||||
if (m_codec_context != nullptr) {
|
||||
avcodec_free_context(&m_codec_context);
|
||||
}
|
||||
}
|
||||
|
||||
bool WriteFrame(const AVFrame* frame, void* output, size_t output_size, size_t* output_offset,
|
||||
AjmGaplessState* gapless, AjmDecodeResult* result) {
|
||||
if (frame == nullptr || output_offset == nullptr || result == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto channels = static_cast<uint32_t>(std::max(frame->ch_layout.nb_channels, 1));
|
||||
const auto bpf = channels * AjmBytesPerSample(m_sample_encoding);
|
||||
if (bpf == 0) {
|
||||
result->result = AJM_RESULT_INVALID_PARAMETER;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetFormat(channels, static_cast<uint32_t>(std::max(frame->sample_rate, 1)),
|
||||
m_sample_encoding);
|
||||
if (m_codec_context != nullptr && m_codec_context->bit_rate > 0) {
|
||||
m_bitrate = static_cast<uint32_t>(m_codec_context->bit_rate);
|
||||
} else if (m_have_header) {
|
||||
m_bitrate = m_last_header.bitrate;
|
||||
}
|
||||
|
||||
uint32_t skip_samples = 0;
|
||||
if (gapless != nullptr && gapless->current.skip_samples > 0) {
|
||||
skip_samples = std::min<uint32_t>(frame->nb_samples, gapless->current.skip_samples);
|
||||
gapless->current.skip_samples =
|
||||
static_cast<uint16_t>(gapless->current.skip_samples - skip_samples);
|
||||
}
|
||||
|
||||
uint32_t samples_to_write = static_cast<uint32_t>(frame->nb_samples) - skip_samples;
|
||||
if (gapless != nullptr && gapless->HasSampleLimit()) {
|
||||
samples_to_write = std::min(samples_to_write, gapless->current.total_samples);
|
||||
}
|
||||
|
||||
const auto requested_bytes = static_cast<size_t>(samples_to_write) * bpf;
|
||||
auto writable_bytes = requested_bytes;
|
||||
if (output == nullptr || *output_offset >= output_size) {
|
||||
writable_bytes = 0;
|
||||
} else {
|
||||
writable_bytes = std::min(writable_bytes, output_size - *output_offset);
|
||||
writable_bytes -= writable_bytes % bpf;
|
||||
}
|
||||
|
||||
if (writable_bytes != 0) {
|
||||
auto* dst = static_cast<uint8_t*>(output) + *output_offset;
|
||||
const auto* src = frame->data[0] + static_cast<size_t>(skip_samples) * bpf;
|
||||
std::memcpy(dst, src, writable_bytes);
|
||||
*output_offset += writable_bytes;
|
||||
}
|
||||
|
||||
const auto samples_written = static_cast<uint32_t>(writable_bytes / bpf);
|
||||
if (gapless != nullptr && gapless->HasSampleLimit()) {
|
||||
gapless->current.total_samples -=
|
||||
std::min(gapless->current.total_samples, samples_written);
|
||||
}
|
||||
if (gapless != nullptr) {
|
||||
const auto skipped_total =
|
||||
std::min<uint32_t>(std::numeric_limits<uint16_t>::max(),
|
||||
static_cast<uint32_t>(gapless->current.skipped_samples) +
|
||||
skip_samples + (samples_to_write - samples_written));
|
||||
gapless->current.skipped_samples = static_cast<uint16_t>(skipped_total);
|
||||
}
|
||||
|
||||
m_total_decoded_samples += samples_written;
|
||||
result->frames++;
|
||||
result->total_decoded_samples = m_total_decoded_samples;
|
||||
result->format = GetFormat();
|
||||
|
||||
if (writable_bytes != requested_bytes) {
|
||||
result->result |= AJM_RESULT_NOT_ENOUGH_ROOM;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodePacket(const uint8_t* packet_data, int packet_size, void* output, size_t output_size,
|
||||
size_t* output_offset, AjmGaplessState* gapless, AjmDecodeResult* result) {
|
||||
if (packet_data == nullptr || packet_size <= 0 || result == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
AVPacket* packet = av_packet_alloc();
|
||||
if (packet == nullptr || av_new_packet(packet, packet_size) < 0) {
|
||||
av_packet_free(&packet);
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return false;
|
||||
}
|
||||
std::memcpy(packet->data, packet_data, static_cast<size_t>(packet_size));
|
||||
|
||||
int rc = avcodec_send_packet(m_codec_context, packet);
|
||||
av_packet_free(&packet);
|
||||
if (rc < 0) {
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
AVFrame* frame = av_frame_alloc();
|
||||
if (frame == nullptr) {
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = avcodec_receive_frame(m_codec_context, frame);
|
||||
if (rc == AVERROR(EAGAIN) || rc == AVERROR_EOF) {
|
||||
av_frame_free(&frame);
|
||||
return true;
|
||||
}
|
||||
if (rc < 0) {
|
||||
av_frame_free(&frame);
|
||||
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_INVALID_DATA;
|
||||
return false;
|
||||
}
|
||||
|
||||
AVFrame* converted = AjmConvertFfmpegFrame(frame, m_sample_encoding, result);
|
||||
av_frame_free(&frame);
|
||||
if (converted == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool ok =
|
||||
WriteFrame(converted, output, output_size, output_offset, gapless, result);
|
||||
av_frame_free(&converted);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AVCodec* m_codec = nullptr;
|
||||
AVCodecContext* m_codec_context = nullptr;
|
||||
AVCodecParserContext* m_parser = nullptr;
|
||||
bool m_have_header = false;
|
||||
uint32_t m_bitrate = 0;
|
||||
AjmMp3FrameHeader m_last_header;
|
||||
};
|
||||
|
||||
} // namespace Libs::Audio::Ajm
|
||||
+2639
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,353 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_AUDIO_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_AUDIO_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
#include "common/subsystems.h"
|
||||
|
||||
namespace Libs::Audio {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Audio);
|
||||
|
||||
namespace AudioOut {
|
||||
|
||||
struct AudioOutOutputParam;
|
||||
struct AudioOutPortState;
|
||||
|
||||
int KYTY_SYSV_ABI AudioOutInit();
|
||||
int KYTY_SYSV_ABI AudioOutOpen(int user_id, int type, int index, uint32_t len, uint32_t freq,
|
||||
uint32_t param);
|
||||
int KYTY_SYSV_ABI AudioOutSetVolume(int handle, uint32_t flag, int* vol);
|
||||
int KYTY_SYSV_ABI AudioOutOutputs(AudioOutOutputParam* param, uint32_t num);
|
||||
int KYTY_SYSV_ABI AudioOutOutput(int handle, const void* ptr);
|
||||
int KYTY_SYSV_ABI AudioOutClose(int handle);
|
||||
int KYTY_SYSV_ABI AudioOutGetPortState(int handle, AudioOutPortState* state);
|
||||
|
||||
} // namespace AudioOut
|
||||
|
||||
namespace AudioOut2 {
|
||||
|
||||
struct AudioOut2ContextParam;
|
||||
struct AudioOut2PortParam;
|
||||
struct AudioOut2Attribute;
|
||||
struct AudioOut2PortState;
|
||||
struct AudioOut2SystemState;
|
||||
struct AudioOut2Position;
|
||||
struct AudioOut2SpeakerInfo;
|
||||
struct AudioOut2SystemDebugStateParam;
|
||||
struct AudioOut2MasteringParamsHeader;
|
||||
struct AudioOut2MasteringStatesHeader;
|
||||
|
||||
using AudioOut2ContextHandle = uint64_t;
|
||||
using AudioOut2PortHandle = uint64_t;
|
||||
using AudioOut2UserHandle = uintptr_t;
|
||||
using AudioOut2SpeakerArrayHandle = void*;
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2Initialize();
|
||||
int KYTY_SYSV_ABI AudioOut2ContextQueryMemory(const AudioOut2ContextParam* params,
|
||||
size_t* memory_size);
|
||||
int KYTY_SYSV_ABI AudioOut2ContextResetParam(AudioOut2ContextParam* params);
|
||||
int KYTY_SYSV_ABI AudioOut2ContextCreate(const AudioOut2ContextParam* params, void* buffer,
|
||||
size_t buffer_size, AudioOut2ContextHandle* ctx);
|
||||
int KYTY_SYSV_ABI AudioOut2ContextDestroy(AudioOut2ContextHandle ctx);
|
||||
int KYTY_SYSV_ABI AudioOut2ContextSetAttributes(AudioOut2ContextHandle ctx,
|
||||
const AudioOut2Attribute* attributes, uint32_t num);
|
||||
int KYTY_SYSV_ABI AudioOut2ContextAdvance(AudioOut2ContextHandle ctx);
|
||||
int KYTY_SYSV_ABI AudioOut2ContextPush(AudioOut2ContextHandle ctx, uint32_t blocking);
|
||||
int KYTY_SYSV_ABI AudioOut2ContextGetQueueLevel(AudioOut2ContextHandle ctx, uint32_t* queue_level,
|
||||
uint32_t* available_queues);
|
||||
int KYTY_SYSV_ABI AudioOut2PortCreate(AudioOut2ContextHandle ctx, const AudioOut2PortParam* params,
|
||||
AudioOut2PortHandle* port);
|
||||
int KYTY_SYSV_ABI AudioOut2PortDestroy(AudioOut2PortHandle port);
|
||||
int KYTY_SYSV_ABI AudioOut2PortSetAttributes(AudioOut2PortHandle port,
|
||||
const AudioOut2Attribute* attributes, uint32_t num);
|
||||
int KYTY_SYSV_ABI AudioOut2PortGetState(AudioOut2PortHandle port, AudioOut2PortState* state);
|
||||
int KYTY_SYSV_ABI AudioOut2GetSystemState(AudioOut2SystemState* state);
|
||||
int KYTY_SYSV_ABI AudioOut2UserCreate(uint32_t user_id, AudioOut2UserHandle* handle);
|
||||
int KYTY_SYSV_ABI AudioOut2UserDestroy(AudioOut2UserHandle handle);
|
||||
size_t KYTY_SYSV_ABI AudioOut2GetSpeakerArrayMemorySize(uint32_t num_speakers, uint8_t is_3d,
|
||||
uint8_t is_ambisonics);
|
||||
int KYTY_SYSV_ABI AudioOut2SpeakerArrayCreate(AudioOut2SpeakerArrayHandle* handle,
|
||||
const void* vbap_params, const void* ambi_params);
|
||||
int KYTY_SYSV_ABI AudioOut2SpeakerArrayDestroy(AudioOut2SpeakerArrayHandle handle);
|
||||
int KYTY_SYSV_ABI AudioOut2GetSpeakerArrayCoefficients(
|
||||
AudioOut2SpeakerArrayHandle handle, AudioOut2Position pos, float spread, float* coefficients,
|
||||
uint32_t num_coefficients, uint8_t height_aware, float downmix_spread_radius);
|
||||
int KYTY_SYSV_ABI AudioOut2GetSpeakerArrayAmbisonicsCoefficients(AudioOut2SpeakerArrayHandle handle,
|
||||
uint32_t ambisonics_channel,
|
||||
float* coefficients,
|
||||
uint32_t num_coefficients);
|
||||
int KYTY_SYSV_ABI AudioOut2GetSpeakerInfo(AudioOut2SpeakerInfo* info, uint32_t flags);
|
||||
int KYTY_SYSV_ABI AudioOut2SetSystemDebugState(const AudioOut2SystemDebugStateParam* param);
|
||||
int KYTY_SYSV_ABI AudioOut2Set3DLatency(uint32_t user_id, uint32_t output, uint32_t latency_us);
|
||||
int KYTY_SYSV_ABI AudioOut2MasteringInit(uint32_t flags);
|
||||
int KYTY_SYSV_ABI AudioOut2MasteringSetParam(const AudioOut2MasteringParamsHeader* param,
|
||||
uint32_t output, uint32_t flags);
|
||||
int KYTY_SYSV_ABI AudioOut2MasteringGetState(AudioOut2MasteringStatesHeader* state, uint32_t output,
|
||||
AudioOut2UserHandle user);
|
||||
int KYTY_SYSV_ABI AudioOut2MasteringTerm();
|
||||
|
||||
} // namespace AudioOut2
|
||||
|
||||
namespace AudioIn {
|
||||
|
||||
int KYTY_SYSV_ABI AudioInOpen(int user_id, uint32_t type, uint32_t index, uint32_t len,
|
||||
uint32_t freq, uint32_t param);
|
||||
int KYTY_SYSV_ABI AudioInInput(int handle, void* dest);
|
||||
|
||||
} // namespace AudioIn
|
||||
|
||||
namespace VoiceQoS {
|
||||
|
||||
int KYTY_SYSV_ABI VoiceQoSInit(void* mem_block, uint32_t mem_size, int32_t app_type);
|
||||
|
||||
} // namespace VoiceQoS
|
||||
|
||||
namespace Ajm {
|
||||
|
||||
struct AjmBatchInfo;
|
||||
struct AjmBatchError;
|
||||
struct AjmBuffer;
|
||||
|
||||
struct AjmDecAt9ConfigDataInfo {
|
||||
uint32_t channels;
|
||||
uint32_t sample_rate;
|
||||
uint32_t frame_samples_per_channel;
|
||||
uint32_t superframe_samples_per_channel;
|
||||
uint32_t superframe_size;
|
||||
};
|
||||
|
||||
int KYTY_SYSV_ABI AjmInitialize(int64_t reserved, uint32_t* context);
|
||||
int KYTY_SYSV_ABI AjmModuleRegister(uint32_t context, uint32_t codec, int64_t reserved);
|
||||
int KYTY_SYSV_ABI AjmModuleUnregister(uint32_t context, uint32_t codec);
|
||||
int KYTY_SYSV_ABI AjmFinalize(uint32_t context);
|
||||
int KYTY_SYSV_ABI AjmInstanceCreate(uint32_t context, uint32_t codec, uint64_t flags,
|
||||
uint32_t* instance);
|
||||
int KYTY_SYSV_ABI AjmInstanceDestroy(uint32_t context, uint32_t instance);
|
||||
int KYTY_SYSV_ABI AjmMemoryRegister(uint32_t context, void* ptr, size_t pages);
|
||||
int KYTY_SYSV_ABI AjmMemoryUnregister(uint32_t context, void* ptr);
|
||||
int KYTY_SYSV_ABI AjmBatchInitialize(void* buffer, size_t size, AjmBatchInfo* info);
|
||||
int KYTY_SYSV_ABI AjmBatchStart(uint32_t context, const AjmBatchInfo* info, int priority,
|
||||
AjmBatchError* error, uint32_t* batch);
|
||||
int KYTY_SYSV_ABI AjmBatchWait(uint32_t context, uint32_t batch, uint32_t timeout,
|
||||
AjmBatchError* error);
|
||||
int KYTY_SYSV_ABI AjmBatchCancel(uint32_t context, uint32_t batch);
|
||||
int KYTY_SYSV_ABI AjmBatchErrorDump(const AjmBatchInfo* info, AjmBatchError* error);
|
||||
int KYTY_SYSV_ABI AjmBatchJobInitialize(AjmBatchInfo* info, uint32_t instance,
|
||||
const void* codec_parameters, size_t codec_parameters_size,
|
||||
void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobClearContext(AjmBatchInfo* info, uint32_t instance, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobDecode(AjmBatchInfo* info, uint32_t instance,
|
||||
const void* bitstream_input, size_t bitstream_input_size,
|
||||
void* pcm_output, size_t pcm_output_size, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobDecodeSingle(AjmBatchInfo* info, uint32_t instance,
|
||||
const void* bitstream_input, size_t bitstream_input_size,
|
||||
void* pcm_output, size_t pcm_output_size, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobDecodeSplit(AjmBatchInfo* info, uint32_t instance,
|
||||
const AjmBuffer* input_buffers, size_t input_buffers_num,
|
||||
const AjmBuffer* output_buffers, size_t output_buffers_num,
|
||||
void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobEncode(AjmBatchInfo* info, uint32_t instance, const void* pcm_input,
|
||||
size_t pcm_input_size, void* bitstream_output,
|
||||
size_t bitstream_output_size, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobGetInfo(AjmBatchInfo* info, uint32_t instance, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobGetCodecInfo(AjmBatchInfo* info, uint32_t instance, void* result,
|
||||
size_t result_size);
|
||||
int KYTY_SYSV_ABI AjmBatchJobSetGaplessDecode(AjmBatchInfo* info, uint32_t instance,
|
||||
const void* gapless_decode, int reset, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobGetGaplessDecode(AjmBatchInfo* info, uint32_t instance, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobSetResampleParameters(AjmBatchInfo* info, uint32_t instance,
|
||||
float ratio, uint32_t flags, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobSetResampleParametersEx(AjmBatchInfo* info, uint32_t instance,
|
||||
float ratio_start,
|
||||
float ratio_change_per_sample, uint32_t flags,
|
||||
void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobGetResampleInfo(AjmBatchInfo* info, uint32_t instance, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobGetStatistics(AjmBatchInfo* info, float interval, void* result);
|
||||
int KYTY_SYSV_ABI AjmBatchJobControl(AjmBatchInfo* info, uint32_t instance, uint64_t flags,
|
||||
const void* sideband_input, size_t sideband_input_size,
|
||||
void* sideband_output, size_t sideband_output_size);
|
||||
int KYTY_SYSV_ABI AjmBatchJobRun(AjmBatchInfo* info, uint32_t instance, uint64_t flags,
|
||||
const void* data_input, size_t data_input_size, void* data_output,
|
||||
size_t data_output_size, void* sideband_output,
|
||||
size_t sideband_output_size);
|
||||
int KYTY_SYSV_ABI AjmBatchJobRunSplit(AjmBatchInfo* info, uint32_t instance, uint64_t flags,
|
||||
const AjmBuffer* input_buffers, size_t input_buffers_num,
|
||||
const AjmBuffer* output_buffers, size_t output_buffers_num,
|
||||
void* sideband_output, size_t sideband_output_size);
|
||||
int KYTY_SYSV_ABI AjmDecAt9ParseConfigData(const void* config_data,
|
||||
AjmDecAt9ConfigDataInfo* config_info);
|
||||
const char* KYTY_SYSV_ABI AjmStrError(int error);
|
||||
|
||||
} // namespace Ajm
|
||||
|
||||
namespace Acm {
|
||||
|
||||
struct AcmBatchInfo;
|
||||
struct AcmBatchError;
|
||||
|
||||
using AcmContextId = uint32_t;
|
||||
using AcmBatchId = uint32_t;
|
||||
|
||||
int KYTY_SYSV_ABI AcmContextCreate(AcmContextId* context);
|
||||
int KYTY_SYSV_ABI AcmContextDestroy(AcmContextId context);
|
||||
int KYTY_SYSV_ABI AcmBatchStartBuffer(AcmContextId context, const void* batch_commands,
|
||||
size_t batch_size, AcmBatchError* batch_error,
|
||||
AcmBatchId* batch);
|
||||
int KYTY_SYSV_ABI AcmBatchStartBuffers(AcmContextId context, uint32_t batch_info_count,
|
||||
const AcmBatchInfo* const batch_info[],
|
||||
AcmBatchError* batch_error, AcmBatchId* batch);
|
||||
int KYTY_SYSV_ABI AcmBatchWait(AcmContextId context, AcmBatchId batch, uint32_t timeout);
|
||||
int KYTY_SYSV_ABI AcmBatchJobNotification(AcmBatchInfo* batch_info);
|
||||
int KYTY_SYSV_ABI AcmConvReverbSharedInput(AcmBatchInfo* batch_info, uint32_t block_count, void* in,
|
||||
uint32_t count, const void* const ir[],
|
||||
const float* gain, void* const out[]);
|
||||
int KYTY_SYSV_ABI AcmConvReverbSharedIr(AcmBatchInfo* batch_info, uint32_t block_count,
|
||||
const void* ir, uint32_t count, void* const in[],
|
||||
const float* gain, void* const out[]);
|
||||
int KYTY_SYSV_ABI AcmFft(AcmBatchInfo* batch_info, int size, int count, int input_format,
|
||||
const void* const input[], int output_format, void* const output[],
|
||||
uint32_t flags);
|
||||
int KYTY_SYSV_ABI AcmIfft(AcmBatchInfo* batch_info, int size, int count, int input_format,
|
||||
const void* const input[], int output_format, void* const output[],
|
||||
uint32_t flags);
|
||||
int KYTY_SYSV_ABI AcmPanner(AcmBatchInfo* batch_info, uint32_t in_count, const float* const in[],
|
||||
uint32_t biquad_count, uint32_t biquad_update_count, uint32_t out_count,
|
||||
const void* const parameter[], void* const state[],
|
||||
const float* const out_init[], float* const out[]);
|
||||
|
||||
} // namespace Acm
|
||||
|
||||
namespace AvPlayer {
|
||||
|
||||
struct AvPlayerInitData;
|
||||
struct AvPlayerFrameInfoEx;
|
||||
struct AvPlayerFrameInfo;
|
||||
struct AvPlayerInternal;
|
||||
|
||||
using Bool = uint8_t;
|
||||
|
||||
AvPlayerInternal* KYTY_SYSV_ABI AvPlayerInit(AvPlayerInitData* init);
|
||||
int KYTY_SYSV_ABI AvPlayerInitEx(const void* init_ex, AvPlayerInternal** handle);
|
||||
int KYTY_SYSV_ABI AvPlayerPostInit(AvPlayerInternal* h, const void* post_init);
|
||||
int KYTY_SYSV_ABI AvPlayerAddSource(AvPlayerInternal* h, const char* filename);
|
||||
int KYTY_SYSV_ABI AvPlayerAddSourceEx(AvPlayerInternal* h, uint32_t uri_type,
|
||||
const void* source_details);
|
||||
int KYTY_SYSV_ABI AvPlayerStreamCount(AvPlayerInternal* h);
|
||||
int KYTY_SYSV_ABI AvPlayerGetStreamInfo(AvPlayerInternal* h, uint32_t stream_id, void* info);
|
||||
int KYTY_SYSV_ABI AvPlayerGetStreamInfoEx(AvPlayerInternal* h, uint32_t stream_id, void* info);
|
||||
int KYTY_SYSV_ABI AvPlayerEnableStream(AvPlayerInternal* h, uint32_t stream_id);
|
||||
int KYTY_SYSV_ABI AvPlayerDisableStream(AvPlayerInternal* h, uint32_t stream_id);
|
||||
int KYTY_SYSV_ABI AvPlayerChangeStream(AvPlayerInternal* h, uint32_t old_stream_id,
|
||||
uint32_t new_stream_id);
|
||||
int KYTY_SYSV_ABI AvPlayerStart(AvPlayerInternal* h);
|
||||
int KYTY_SYSV_ABI AvPlayerStartEx(AvPlayerInternal* h, const void* start_info_ex);
|
||||
int KYTY_SYSV_ABI AvPlayerStop(AvPlayerInternal* h);
|
||||
int KYTY_SYSV_ABI AvPlayerPause(AvPlayerInternal* h);
|
||||
int KYTY_SYSV_ABI AvPlayerResume(AvPlayerInternal* h);
|
||||
int KYTY_SYSV_ABI AvPlayerSetLooping(AvPlayerInternal* h, Bool loop);
|
||||
int KYTY_SYSV_ABI AvPlayerSetTrickSpeed(AvPlayerInternal* h, int32_t trick_speed);
|
||||
int KYTY_SYSV_ABI AvPlayerSetAvSyncMode(AvPlayerInternal* h, uint32_t sync_mode);
|
||||
int KYTY_SYSV_ABI AvPlayerSetAvailableBandwidth(AvPlayerInternal* h, uint32_t start_bandwidth,
|
||||
uint32_t minimum_bandwidth,
|
||||
uint32_t maximum_bandwidth);
|
||||
Bool KYTY_SYSV_ABI AvPlayerGetVideoData(AvPlayerInternal* h, AvPlayerFrameInfo* video_info);
|
||||
Bool KYTY_SYSV_ABI AvPlayerGetVideoDataEx(AvPlayerInternal* h, AvPlayerFrameInfoEx* video_info);
|
||||
Bool KYTY_SYSV_ABI AvPlayerGetAudioData(AvPlayerInternal* h, AvPlayerFrameInfo* audio_info);
|
||||
Bool KYTY_SYSV_ABI AvPlayerIsActive(AvPlayerInternal* h);
|
||||
uint64_t KYTY_SYSV_ABI AvPlayerCurrentTime(AvPlayerInternal* h);
|
||||
int KYTY_SYSV_ABI AvPlayerJumpToTime(AvPlayerInternal* h, uint64_t time_ms);
|
||||
int KYTY_SYSV_ABI AvPlayerClose(AvPlayerInternal* h);
|
||||
int KYTY_SYSV_ABI AvPlayerSetLogCallback(void* callback, void* user_data);
|
||||
|
||||
} // namespace AvPlayer
|
||||
|
||||
namespace Audio3d {
|
||||
|
||||
struct Audio3dOpenParameters;
|
||||
|
||||
int KYTY_SYSV_ABI Audio3dInitialize(int64_t reserved);
|
||||
void KYTY_SYSV_ABI Audio3dGetDefaultOpenParameters(Audio3dOpenParameters* p);
|
||||
int KYTY_SYSV_ABI Audio3dPortOpen(int user_id, const Audio3dOpenParameters* parameters,
|
||||
uint32_t* id);
|
||||
int KYTY_SYSV_ABI Audio3dPortSetAttribute(uint32_t port_id, uint32_t attribute_id,
|
||||
const void* attribute, size_t attribute_size);
|
||||
int KYTY_SYSV_ABI Audio3dPortGetQueueLevel(uint32_t port_id, uint32_t* queue_level,
|
||||
uint32_t* queue_available);
|
||||
int KYTY_SYSV_ABI Audio3dPortAdvance(uint32_t port_id);
|
||||
int KYTY_SYSV_ABI Audio3dPortPush(uint32_t port_id, uint32_t blocking);
|
||||
|
||||
} // namespace Audio3d
|
||||
|
||||
namespace Ngs2 {
|
||||
|
||||
struct Ngs2SystemOption;
|
||||
struct Ngs2RackOption;
|
||||
struct Ngs2BufferAllocator;
|
||||
struct Ngs2VoiceParamHeader;
|
||||
struct Ngs2RenderBufferInfo;
|
||||
struct Ngs2ContextBufferInfo;
|
||||
struct Ngs2VoiceState;
|
||||
struct Ngs2WaveformFormat;
|
||||
struct Ngs2WaveformBlock;
|
||||
struct Ngs2WaveformInfo;
|
||||
struct Ngs2PanWork;
|
||||
struct Ngs2PanParam;
|
||||
struct Ngs2GeomListenerParam;
|
||||
struct Ngs2GeomListenerWork;
|
||||
struct Ngs2GeomSourceParam;
|
||||
struct Ngs2GeomAttribute;
|
||||
|
||||
int KYTY_SYSV_ABI Ngs2SystemResetOption(Ngs2SystemOption* option);
|
||||
int KYTY_SYSV_ABI Ngs2SystemQueryBufferSize(const Ngs2SystemOption* option,
|
||||
Ngs2ContextBufferInfo* buffer_info);
|
||||
int KYTY_SYSV_ABI Ngs2SystemCreate(const Ngs2SystemOption* option,
|
||||
const Ngs2ContextBufferInfo* buffer_info, uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2SystemSetGrainSamples(uintptr_t system_handle, uint32_t num_samples);
|
||||
int KYTY_SYSV_ABI Ngs2RackQueryBufferSize(uint32_t rack_id, const Ngs2RackOption* option,
|
||||
Ngs2ContextBufferInfo* buffer_info);
|
||||
int KYTY_SYSV_ABI Ngs2RackCreate(uintptr_t system_handle, uint32_t rack_id,
|
||||
const Ngs2RackOption* option,
|
||||
const Ngs2ContextBufferInfo* buffer_info, uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2SystemCreateWithAllocator(const Ngs2SystemOption* option,
|
||||
const Ngs2BufferAllocator* allocator,
|
||||
uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2SystemDestroy(uintptr_t system_handle, Ngs2ContextBufferInfo* buffer_info);
|
||||
int KYTY_SYSV_ABI Ngs2RackCreateWithAllocator(uintptr_t system_handle, uint32_t rack_id,
|
||||
const Ngs2RackOption* option,
|
||||
const Ngs2BufferAllocator* allocator,
|
||||
uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2RackDestroy(uintptr_t rack_handle, Ngs2ContextBufferInfo* buffer_info);
|
||||
int KYTY_SYSV_ABI Ngs2RackLock(uintptr_t rack_handle);
|
||||
int KYTY_SYSV_ABI Ngs2RackUnlock(uintptr_t rack_handle);
|
||||
int KYTY_SYSV_ABI Ngs2RackGetVoiceHandle(uintptr_t rack_handle, uint32_t voice_id,
|
||||
uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceControl(uintptr_t voice_handle, const Ngs2VoiceParamHeader* param_list);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceRunCommands(uintptr_t voice_handle, const void* commands,
|
||||
uint32_t num_commands, uint32_t flags);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* state,
|
||||
size_t state_size);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceGetStateFlags(uintptr_t voice_handle, uint32_t* state_flags);
|
||||
int KYTY_SYSV_ABI Ngs2SystemRender(uintptr_t system_handle, const Ngs2RenderBufferInfo* buffer_info,
|
||||
uint32_t num_buffer_info);
|
||||
int KYTY_SYSV_ABI Ngs2ParseWaveformData(const void* data, size_t data_size, Ngs2WaveformInfo* info);
|
||||
int KYTY_SYSV_ABI Ngs2CalcWaveformBlock(const Ngs2WaveformFormat* format, uint32_t sample_pos,
|
||||
uint32_t num_samples, Ngs2WaveformBlock* block);
|
||||
int KYTY_SYSV_ABI Ngs2PanInit(Ngs2PanWork* work, const float* speaker_angles, float unit_angle,
|
||||
uint32_t num_speakers);
|
||||
int KYTY_SYSV_ABI Ngs2PanGetVolumeMatrix(Ngs2PanWork* work, const Ngs2PanParam* params,
|
||||
uint32_t num_params, uint32_t matrix_format,
|
||||
float* out_volume_matrix);
|
||||
int KYTY_SYSV_ABI Ngs2GeomResetListenerParam(Ngs2GeomListenerParam* out_listener_param);
|
||||
int KYTY_SYSV_ABI Ngs2GeomResetSourceParam(Ngs2GeomSourceParam* out_source_param);
|
||||
int KYTY_SYSV_ABI Ngs2GeomCalcListener(const Ngs2GeomListenerParam* param,
|
||||
Ngs2GeomListenerWork* out_work, uint32_t flags);
|
||||
int KYTY_SYSV_ABI Ngs2GeomApply(const Ngs2GeomListenerWork* listener,
|
||||
const Ngs2GeomSourceParam* source, Ngs2GeomAttribute* out_attrib,
|
||||
uint32_t flags);
|
||||
|
||||
} // namespace Ngs2
|
||||
|
||||
} // namespace Libs::Audio
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_AUDIO_H_ */
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_AUDIO_INTERNAL_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_AUDIO_INTERNAL_H_
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
namespace Libs::Audio::AudioInternal {
|
||||
|
||||
enum class Format {
|
||||
Unknown,
|
||||
Signed16bitMono,
|
||||
Signed16bitStereo,
|
||||
Signed16bit8Ch,
|
||||
FloatMono,
|
||||
FloatStereo,
|
||||
Float8Ch,
|
||||
Signed16bit8ChStd,
|
||||
Float8ChStd,
|
||||
};
|
||||
|
||||
struct OutputParam {
|
||||
int handle = 0;
|
||||
const void* data = nullptr;
|
||||
};
|
||||
|
||||
static constexpr int OUT_PORTS_MAX = 32;
|
||||
|
||||
int AudioOutOpen(int type, uint32_t samples_num, uint32_t freq, Format format);
|
||||
void AudioOutClose(int handle);
|
||||
uint32_t AudioOutOutputs(const OutputParam* params, uint32_t num);
|
||||
|
||||
} // namespace Libs::Audio::AudioInternal
|
||||
|
||||
#endif // EMULATOR_INCLUDE_EMULATOR_AUDIO_INTERNAL_H_
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,546 @@
|
||||
#include "libs/controller.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/threads.h"
|
||||
#include "kernel/pthread.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "libs/padData.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs::Controller {
|
||||
|
||||
LIB_NAME("Pad", "Pad");
|
||||
|
||||
constexpr int PAD_ERROR_INVALID_ARG = -2137915391; /* 0x80920001 */
|
||||
constexpr int PAD_ERROR_INVALID_HANDLE = -2137915389; /* 0x80920003 */
|
||||
|
||||
struct PadControllerInformation {
|
||||
float touch_pixel_density;
|
||||
uint16_t touch_resolution_x;
|
||||
uint16_t touch_resolution_y;
|
||||
uint8_t stick_dead_zone_left;
|
||||
uint8_t stick_dead_zone_right;
|
||||
uint8_t connection_type;
|
||||
uint8_t connected_count;
|
||||
bool connected;
|
||||
int device_class;
|
||||
uint8_t reserve[8];
|
||||
};
|
||||
|
||||
struct PadVibrationParam {
|
||||
uint8_t large_motor;
|
||||
uint8_t small_motor;
|
||||
};
|
||||
|
||||
struct ControllerState {
|
||||
uint64_t time = 0;
|
||||
uint32_t buttons = 0;
|
||||
int axes[static_cast<int>(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0};
|
||||
};
|
||||
|
||||
class GameController {
|
||||
public:
|
||||
GameController() = default;
|
||||
virtual ~GameController() = default;
|
||||
|
||||
KYTY_CLASS_NO_COPY(GameController);
|
||||
|
||||
void Connect(int id);
|
||||
void Disconnect(int id);
|
||||
void Button(int id, uint32_t button, bool down);
|
||||
void Axis(int id, Axis axis, int value);
|
||||
void GetConnectionInfo(bool* flag, int* count);
|
||||
void ReadState(ControllerState* state, bool* flag, int* count);
|
||||
int ReadStates(ControllerState* states, int states_num, bool* flag, int* count);
|
||||
|
||||
private:
|
||||
static constexpr uint32_t STATES_MAX = 64;
|
||||
|
||||
struct StatePrivate {
|
||||
bool obtained = false;
|
||||
};
|
||||
|
||||
void CheckActive();
|
||||
[[nodiscard]] ControllerState GetLastState() const;
|
||||
void AddState(const ControllerState& state);
|
||||
|
||||
Common::Mutex m_mutex;
|
||||
std::vector<int> m_connected_ids;
|
||||
int m_active_id = -1;
|
||||
bool m_connected = false;
|
||||
int m_connected_count = 0;
|
||||
ControllerState m_states[STATES_MAX];
|
||||
StatePrivate m_private[STATES_MAX];
|
||||
ControllerState m_last_state;
|
||||
uint32_t m_states_num = 0;
|
||||
uint32_t m_first_state = 0;
|
||||
};
|
||||
|
||||
static GameController* g_controller = nullptr;
|
||||
|
||||
static constexpr int KEYBOARD_CONTROLLER_ID = -1000;
|
||||
|
||||
static uint8_t pad_connected_count_to_u8(int connected_count) {
|
||||
return static_cast<uint8_t>(connected_count > 255 ? 255 : connected_count);
|
||||
}
|
||||
|
||||
static void pad_fill_data(PadData* data, const ControllerState& state, bool connected,
|
||||
int connected_count) {
|
||||
EXIT_IF(data == nullptr);
|
||||
|
||||
std::memset(data, 0, sizeof(*data));
|
||||
|
||||
data->buttons = state.buttons;
|
||||
data->left_stick_x = state.axes[static_cast<int>(Axis::LeftX)];
|
||||
data->left_stick_y = state.axes[static_cast<int>(Axis::LeftY)];
|
||||
data->right_stick_x = state.axes[static_cast<int>(Axis::RightX)];
|
||||
data->right_stick_y = state.axes[static_cast<int>(Axis::RightY)];
|
||||
data->analog_buttons_l2 = state.axes[static_cast<int>(Axis::TriggerLeft)];
|
||||
data->analog_buttons_r2 = state.axes[static_cast<int>(Axis::TriggerRight)];
|
||||
data->orientation_w = 1.0f;
|
||||
data->touch_data_touch0_id = 1;
|
||||
data->touch_data_touch1_id = 2;
|
||||
data->connected = connected;
|
||||
data->timestamp = state.time;
|
||||
data->connected_count = pad_connected_count_to_u8(connected_count);
|
||||
data->device_unique_data_len = 0;
|
||||
}
|
||||
|
||||
KYTY_SUBSYSTEM_INIT(Controller) {
|
||||
EXIT_IF(g_controller != nullptr);
|
||||
|
||||
g_controller = new GameController;
|
||||
g_controller->Connect(KEYBOARD_CONTROLLER_ID);
|
||||
}
|
||||
|
||||
KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Controller) {}
|
||||
|
||||
KYTY_SUBSYSTEM_DESTROY(Controller) {}
|
||||
|
||||
void GameController::Connect(int id) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
if (std::find(m_connected_ids.begin(), m_connected_ids.end(), id) != m_connected_ids.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_connected_ids.push_back(id);
|
||||
|
||||
CheckActive();
|
||||
}
|
||||
|
||||
void GameController::Disconnect(int id) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
const auto it = std::find(m_connected_ids.begin(), m_connected_ids.end(), id);
|
||||
EXIT_IF(it == m_connected_ids.end());
|
||||
|
||||
m_connected_ids.erase(it);
|
||||
|
||||
CheckActive();
|
||||
}
|
||||
|
||||
void GameController::CheckActive() {
|
||||
bool reset = false;
|
||||
int new_active_id = -1;
|
||||
bool new_connected = false;
|
||||
|
||||
if (!m_connected_ids.empty()) {
|
||||
new_active_id = m_connected_ids[0];
|
||||
for (const auto id: m_connected_ids) {
|
||||
if (id != KEYBOARD_CONTROLLER_ID) {
|
||||
new_active_id = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
new_connected = true;
|
||||
}
|
||||
|
||||
const bool was_connected = m_connected;
|
||||
|
||||
if (m_connected != new_connected || m_active_id != new_active_id) {
|
||||
m_active_id = new_active_id;
|
||||
m_connected = new_connected;
|
||||
if (!was_connected && new_connected) {
|
||||
m_connected_count++;
|
||||
}
|
||||
reset = true;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
m_states_num = 0;
|
||||
m_last_state = ControllerState();
|
||||
}
|
||||
}
|
||||
|
||||
ControllerState GameController::GetLastState() const {
|
||||
if (m_states_num == 0) {
|
||||
return m_last_state;
|
||||
}
|
||||
|
||||
auto last = (m_first_state + m_states_num - 1) % STATES_MAX;
|
||||
|
||||
return m_states[last];
|
||||
}
|
||||
|
||||
void GameController::AddState(const ControllerState& state) {
|
||||
if (m_states_num >= STATES_MAX) {
|
||||
m_states_num = STATES_MAX - 1;
|
||||
m_first_state = (m_first_state + 1) % STATES_MAX;
|
||||
}
|
||||
|
||||
auto index = (m_first_state + m_states_num) % STATES_MAX;
|
||||
|
||||
m_states[index] = state;
|
||||
m_last_state = state;
|
||||
|
||||
m_private[index].obtained = false;
|
||||
|
||||
m_states_num++;
|
||||
}
|
||||
|
||||
void GameController::Button(int id, uint32_t button, bool down) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
if (m_active_id == id) {
|
||||
auto state = GetLastState();
|
||||
|
||||
state.time = LibKernel::KernelGetProcessTime();
|
||||
|
||||
if (down) {
|
||||
state.buttons |= button;
|
||||
} else {
|
||||
state.buttons &= ~button;
|
||||
}
|
||||
|
||||
AddState(state);
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::Axis(int id, Controller::Axis axis, int value) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
if (m_active_id == id) {
|
||||
auto state = GetLastState();
|
||||
|
||||
state.time = LibKernel::KernelGetProcessTime();
|
||||
|
||||
int axis_id = static_cast<int>(axis);
|
||||
|
||||
EXIT_IF(axis_id < 0 || axis_id >= static_cast<int>(Controller::Axis::AxisMax));
|
||||
|
||||
state.axes[axis_id] = value;
|
||||
|
||||
if (axis == Controller::Axis::TriggerLeft) {
|
||||
if (value > 0) {
|
||||
state.buttons |= PAD_BUTTON_L2;
|
||||
} else {
|
||||
state.buttons &= ~PAD_BUTTON_L2;
|
||||
}
|
||||
}
|
||||
|
||||
if (axis == Controller::Axis::TriggerRight) {
|
||||
if (value > 0) {
|
||||
state.buttons |= PAD_BUTTON_R2;
|
||||
} else {
|
||||
state.buttons &= ~PAD_BUTTON_R2;
|
||||
}
|
||||
}
|
||||
|
||||
AddState(state);
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::GetConnectionInfo(bool* flag, int* count) {
|
||||
EXIT_IF(flag == nullptr);
|
||||
EXIT_IF(count == nullptr);
|
||||
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
*flag = m_connected;
|
||||
*count = m_connected_count;
|
||||
}
|
||||
|
||||
void GameController::ReadState(ControllerState* state, bool* flag, int* count) {
|
||||
EXIT_IF(flag == nullptr);
|
||||
EXIT_IF(count == nullptr);
|
||||
EXIT_IF(state == nullptr);
|
||||
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
*flag = m_connected;
|
||||
*count = m_connected_count;
|
||||
*state = GetLastState();
|
||||
}
|
||||
|
||||
int GameController::ReadStates(ControllerState* states, int states_num, bool* flag, int* count) {
|
||||
EXIT_IF(flag == nullptr);
|
||||
EXIT_IF(count == nullptr);
|
||||
EXIT_IF(states == nullptr);
|
||||
EXIT_IF(states_num < 1 || states_num > STATES_MAX);
|
||||
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
*flag = m_connected;
|
||||
*count = m_connected_count;
|
||||
|
||||
int ret_num = 0;
|
||||
|
||||
if (m_connected) {
|
||||
if (m_states_num != 0) {
|
||||
for (uint32_t i = 0; i < m_states_num; i++) {
|
||||
if (ret_num >= states_num) {
|
||||
break;
|
||||
}
|
||||
auto index = (m_first_state + i) % STATES_MAX;
|
||||
if (!m_private[index].obtained) {
|
||||
m_private[index].obtained = true;
|
||||
|
||||
states[ret_num++] = m_states[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret_num;
|
||||
}
|
||||
|
||||
void ControllerConnect(int id) {
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
|
||||
g_controller->Connect(id);
|
||||
}
|
||||
|
||||
void ControllerDisconnect(int id) {
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
|
||||
g_controller->Disconnect(id);
|
||||
}
|
||||
|
||||
void ControllerButton(int id, uint32_t button, bool down) {
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
|
||||
g_controller->Button(id, button, down);
|
||||
}
|
||||
|
||||
void ControllerAxis(int id, Axis axis, int value) {
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
|
||||
g_controller->Axis(id, axis, value);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadInit() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadOpen(int user_id, int type, int index, const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t user_id = %d\n"
|
||||
"\t type = %d\n"
|
||||
"\t index = %d\n"
|
||||
"\t param = 0x%016" PRIx64 "\n",
|
||||
user_id, type, index, reinterpret_cast<uint64_t>(param));
|
||||
|
||||
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
||||
|
||||
if (user_id != 1000 || (type != 0 && type != 2 && type != 16) || index != 0) {
|
||||
return pad_error_invalid_arg;
|
||||
}
|
||||
|
||||
int handle = 1;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadGetHandle(int user_id, int type, int index) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t user_id = %d\n"
|
||||
"\t type = %d\n"
|
||||
"\t index = %d\n",
|
||||
user_id, type, index);
|
||||
|
||||
constexpr int pad_error_device_no_handle = -2137915384; /* 0x80920008 */
|
||||
|
||||
if (user_id != 1000 || (type != 0 && type != 2 && type != 16) || index != 0) {
|
||||
return pad_error_device_no_handle;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
LOGF("\t enable = %s\n", (enable ? "true" : "false"));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadSetAngularVelocityDeadbandState(int handle, bool enable) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
LOGF("\t enable = %s\n", (enable ? "true" : "false"));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadResetOrientation(int handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformation* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
|
||||
int connected_count = 0;
|
||||
bool connected = false;
|
||||
|
||||
g_controller->GetConnectionInfo(&connected, &connected_count);
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (info == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::memset(info, 0, sizeof(*info));
|
||||
|
||||
info->touch_pixel_density = 44.86f;
|
||||
info->touch_resolution_x = 1920;
|
||||
info->touch_resolution_y = 943;
|
||||
info->stick_dead_zone_left = controller_get_axis(-32768, 32767, 8000) - 128;
|
||||
info->stick_dead_zone_right = controller_get_axis(-32768, 32767, 8000) - 128;
|
||||
info->connection_type = 0;
|
||||
info->connected_count = pad_connected_count_to_u8(connected_count);
|
||||
info->connected = connected;
|
||||
info->device_class = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadReadState(int handle, PadData* data) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (data == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
|
||||
int connected_count = 0;
|
||||
bool connected = false;
|
||||
ControllerState state;
|
||||
|
||||
g_controller->ReadState(&state, &connected, &connected_count);
|
||||
|
||||
pad_fill_data(data, state, connected, connected_count);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadRead(int handle, PadData* data, int num) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(num < 1 || num > 64);
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (data == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::memset(data, 0, sizeof(PadData) * static_cast<size_t>(num));
|
||||
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
|
||||
int connected_count = 0;
|
||||
bool connected = false;
|
||||
ControllerState states[64] = {};
|
||||
|
||||
int ret_num = g_controller->ReadStates(states, num, &connected, &connected_count);
|
||||
|
||||
if (!connected || ret_num == 0) {
|
||||
if (connected) {
|
||||
g_controller->ReadState(&states[0], &connected, &connected_count);
|
||||
}
|
||||
ret_num = 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ret_num; i++) {
|
||||
pad_fill_data(&data[i], states[i], connected, connected_count);
|
||||
}
|
||||
|
||||
return ret_num;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
LOGF("\t large_motor = %d\n"
|
||||
"\t small_motor = %d\n",
|
||||
static_cast<int>(param->large_motor), static_cast<int>(param->small_motor));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadResetLightBar(int handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadSetLightBar(int handle, const PadLightBarParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace Libs::Controller
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_CONTROLLER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_CONTROLLER_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
#include "common/subsystems.h"
|
||||
|
||||
namespace Libs::Controller {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Controller);
|
||||
|
||||
constexpr uint32_t PAD_BUTTON_L3 = 0x00000002;
|
||||
constexpr uint32_t PAD_BUTTON_R3 = 0x00000004;
|
||||
constexpr uint32_t PAD_BUTTON_OPTIONS = 0x00000008;
|
||||
constexpr uint32_t PAD_BUTTON_UP = 0x00000010;
|
||||
constexpr uint32_t PAD_BUTTON_RIGHT = 0x00000020;
|
||||
constexpr uint32_t PAD_BUTTON_DOWN = 0x00000040;
|
||||
constexpr uint32_t PAD_BUTTON_LEFT = 0x00000080;
|
||||
constexpr uint32_t PAD_BUTTON_L2 = 0x00000100;
|
||||
constexpr uint32_t PAD_BUTTON_R2 = 0x00000200;
|
||||
constexpr uint32_t PAD_BUTTON_L1 = 0x00000400;
|
||||
constexpr uint32_t PAD_BUTTON_R1 = 0x00000800;
|
||||
constexpr uint32_t PAD_BUTTON_TRIANGLE = 0x00001000;
|
||||
constexpr uint32_t PAD_BUTTON_CIRCLE = 0x00002000;
|
||||
constexpr uint32_t PAD_BUTTON_CROSS = 0x00004000;
|
||||
constexpr uint32_t PAD_BUTTON_SQUARE = 0x00008000;
|
||||
constexpr uint32_t PAD_BUTTON_TOUCH_PAD = 0x00100000;
|
||||
|
||||
enum class Axis {
|
||||
LeftX = 0,
|
||||
LeftY = 1,
|
||||
RightX = 2,
|
||||
RightY = 3,
|
||||
TriggerLeft = 4,
|
||||
TriggerRight = 5,
|
||||
|
||||
AxisMax
|
||||
};
|
||||
|
||||
struct PadControllerInformation;
|
||||
struct PadData;
|
||||
struct PadVibrationParam;
|
||||
struct PadLightBarParam;
|
||||
|
||||
inline int controller_get_axis(int min, int max, int value) {
|
||||
int v = (255 * (value - min)) / (max - min);
|
||||
return (v < 0 ? 0 : (v > 255 ? 255 : v));
|
||||
}
|
||||
|
||||
void ControllerConnect(int id);
|
||||
void ControllerDisconnect(int id);
|
||||
void ControllerButton(int id, uint32_t button, bool down);
|
||||
void ControllerAxis(int id, Axis axis, int value);
|
||||
|
||||
int KYTY_SYSV_ABI PadInit();
|
||||
int KYTY_SYSV_ABI PadOpen(int user_id, int type, int index, const void* param);
|
||||
int KYTY_SYSV_ABI PadGetHandle(int user_id, int type, int index);
|
||||
int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable);
|
||||
int KYTY_SYSV_ABI PadSetAngularVelocityDeadbandState(int handle, bool enable);
|
||||
int KYTY_SYSV_ABI PadResetOrientation(int handle);
|
||||
int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformation* info);
|
||||
int KYTY_SYSV_ABI PadReadState(int handle, PadData* data);
|
||||
int KYTY_SYSV_ABI PadRead(int handle, PadData* data, int num);
|
||||
int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param);
|
||||
int KYTY_SYSV_ABI PadResetLightBar(int handle);
|
||||
int KYTY_SYSV_ABI PadSetLightBar(int handle, const PadLightBarParam* param);
|
||||
|
||||
} // namespace Libs::Controller
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_CONTROLLER_H_ */
|
||||
@@ -0,0 +1,627 @@
|
||||
#include "libs/dialog.h"
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
// NOLINTNEXTLINE(modernize-concat-nested-namespaces)
|
||||
namespace Libs::Dialog {
|
||||
|
||||
namespace CommonDialog {
|
||||
|
||||
LIB_NAME("CommonDialog", "CommonDialog");
|
||||
|
||||
int KYTY_SYSV_ABI CommonDialogInitialize() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace CommonDialog
|
||||
|
||||
namespace ImeDialog {
|
||||
|
||||
LIB_NAME("ImeDialog", "ImeDialog");
|
||||
|
||||
constexpr int IME_STATUS_NONE = 0;
|
||||
|
||||
int KYTY_SYSV_ABI ImeDialogGetStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
return IME_STATUS_NONE;
|
||||
}
|
||||
|
||||
} // namespace ImeDialog
|
||||
|
||||
namespace LoginDialog {
|
||||
|
||||
LIB_NAME("LoginDialog", "LoginDialog");
|
||||
|
||||
constexpr int LOGIN_STATUS_NONE = 0;
|
||||
constexpr int LOGIN_STATUS_INITIALIZED = 1;
|
||||
constexpr int LOGIN_STATUS_RUNNING = 2;
|
||||
constexpr int LOGIN_STATUS_FINISHED = 3;
|
||||
constexpr int LOGIN_RESULT_OK = 0;
|
||||
constexpr int LOGIN_MODE_ALL_USERS = 0;
|
||||
constexpr int LOGIN_MODE_NOT_LOGGED_IN = 1;
|
||||
constexpr int LOGIN_USER_INVALID = -1;
|
||||
constexpr int LOGIN_USER_ID = 1000;
|
||||
|
||||
constexpr int LOGIN_ERROR_NOT_INITIALIZED = static_cast<int>(0x81340001u);
|
||||
constexpr int LOGIN_ERROR_ALREADY_INITIALIZED = static_cast<int>(0x81340002u);
|
||||
constexpr int LOGIN_ERROR_PARAM_INVALID = static_cast<int>(0x81340003u);
|
||||
constexpr int LOGIN_ERROR_INVALID_STATE = static_cast<int>(0x81340005u);
|
||||
|
||||
struct LoginDialogResult {
|
||||
int32_t result;
|
||||
int32_t selected_user;
|
||||
int32_t reserved[2];
|
||||
};
|
||||
|
||||
struct LoginDialogParam {
|
||||
int32_t size;
|
||||
int32_t mode;
|
||||
int32_t exclude_users_from_login_list[4];
|
||||
int32_t exclude_users_from_logout_list[4];
|
||||
int32_t initial_focus;
|
||||
int32_t reserved[5];
|
||||
};
|
||||
|
||||
static_assert(sizeof(LoginDialogResult) == 16);
|
||||
static_assert(sizeof(LoginDialogParam) == 64);
|
||||
|
||||
static int g_login_status = LOGIN_STATUS_NONE;
|
||||
static int g_login_selected_user = LOGIN_USER_ID;
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogInitialize() {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_login_status != LOGIN_STATUS_NONE) {
|
||||
return LOGIN_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
g_login_status = LOGIN_STATUS_INITIALIZED;
|
||||
g_login_selected_user = LOGIN_USER_ID;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogTerminate() {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_login_status == LOGIN_STATUS_NONE) {
|
||||
return LOGIN_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
g_login_status = LOGIN_STATUS_NONE;
|
||||
g_login_selected_user = LOGIN_USER_ID;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogOpen(const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_login_status != LOGIN_STATUS_INITIALIZED && g_login_status != LOGIN_STATUS_FINISHED) {
|
||||
return LOGIN_ERROR_INVALID_STATE;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return LOGIN_ERROR_PARAM_INVALID;
|
||||
}
|
||||
|
||||
const auto* p = static_cast<const LoginDialogParam*>(param);
|
||||
if (p->size != sizeof(LoginDialogParam) ||
|
||||
(p->mode != LOGIN_MODE_ALL_USERS && p->mode != LOGIN_MODE_NOT_LOGGED_IN)) {
|
||||
return LOGIN_ERROR_PARAM_INVALID;
|
||||
}
|
||||
|
||||
g_login_selected_user =
|
||||
p->initial_focus != LOGIN_USER_INVALID ? p->initial_focus : LOGIN_USER_ID;
|
||||
|
||||
LOGF("\t size = %d\n"
|
||||
"\t mode = %d\n"
|
||||
"\t initial_focus = %d\n"
|
||||
"\t selected_user = %d\n",
|
||||
p->size, p->mode, p->initial_focus, g_login_selected_user);
|
||||
|
||||
g_login_status = LOGIN_STATUS_RUNNING;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogClose() {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_login_status == LOGIN_STATUS_NONE) {
|
||||
return LOGIN_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
g_login_status = LOGIN_STATUS_FINISHED;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogUpdateStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_login_status == LOGIN_STATUS_RUNNING) {
|
||||
g_login_status = LOGIN_STATUS_FINISHED;
|
||||
}
|
||||
|
||||
return g_login_status;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogGetStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
return g_login_status;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogGetResult(void* result) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_login_status == LOGIN_STATUS_NONE) {
|
||||
return LOGIN_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
if (result == nullptr) {
|
||||
return LOGIN_ERROR_PARAM_INVALID;
|
||||
}
|
||||
|
||||
auto* r = static_cast<LoginDialogResult*>(result);
|
||||
r->result = LOGIN_RESULT_OK;
|
||||
r->selected_user = g_login_selected_user;
|
||||
r->reserved[0] = 0;
|
||||
r->reserved[1] = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void KYTY_SYSV_ABI LoginDialogParamInitialize(void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* p = static_cast<LoginDialogParam*>(param);
|
||||
std::memset(p, 0, sizeof(LoginDialogParam));
|
||||
p->size = sizeof(LoginDialogParam);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
p->exclude_users_from_login_list[i] = LOGIN_USER_INVALID;
|
||||
p->exclude_users_from_logout_list[i] = LOGIN_USER_INVALID;
|
||||
}
|
||||
p->initial_focus = LOGIN_USER_INVALID;
|
||||
}
|
||||
|
||||
} // namespace LoginDialog
|
||||
|
||||
namespace SaveDataDialog {
|
||||
|
||||
LIB_NAME("SaveDataDialog", "SaveDataDialog");
|
||||
|
||||
constexpr int SAVE_STATUS_NONE = 0;
|
||||
constexpr int SAVE_STATUS_INITIALIZED = 1;
|
||||
constexpr int SAVE_STATUS_FINISHED = 3;
|
||||
constexpr int SAVE_RESULT_OK = 0;
|
||||
constexpr int SAVE_BUTTON_ID_OK = 1;
|
||||
|
||||
struct SaveDataDialogParam {
|
||||
uint8_t base_param[48];
|
||||
int32_t size;
|
||||
int32_t mode;
|
||||
int32_t disp_type;
|
||||
uint32_t pad0;
|
||||
void* anim_param;
|
||||
void* items;
|
||||
void* user_msg_param;
|
||||
void* sys_msg_param;
|
||||
void* error_code_param;
|
||||
void* prog_bar_param;
|
||||
void* user_data;
|
||||
void* option_param;
|
||||
void* wizard_param;
|
||||
uint8_t reserved[16];
|
||||
};
|
||||
|
||||
struct SaveDataDirName {
|
||||
char data[32];
|
||||
};
|
||||
|
||||
struct SaveDataDialogItems {
|
||||
int32_t user_id;
|
||||
int32_t pad0;
|
||||
const void* title_id;
|
||||
const SaveDataDirName* dir_names;
|
||||
uint32_t dir_names_num;
|
||||
};
|
||||
|
||||
struct SaveDataDialogResult {
|
||||
int32_t mode;
|
||||
int32_t result;
|
||||
int32_t button_id;
|
||||
uint32_t pad0;
|
||||
void* dir_name;
|
||||
void* param;
|
||||
void* user_data;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
static int g_save_status = SAVE_STATUS_NONE;
|
||||
static int g_save_mode = 0;
|
||||
static void* g_save_user_data = nullptr;
|
||||
static char g_save_dir_name[sizeof(SaveDataDirName::data)] {};
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogInitialize() {
|
||||
PRINT_NAME();
|
||||
|
||||
g_save_status = SAVE_STATUS_INITIALIZED;
|
||||
g_save_mode = 0;
|
||||
g_save_user_data = nullptr;
|
||||
g_save_dir_name[0] = '\0';
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogGetStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
return g_save_status;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogUpdateStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
return g_save_status;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogGetResult(void* result) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (result != nullptr) {
|
||||
auto* r = static_cast<SaveDataDialogResult*>(result);
|
||||
r->mode = g_save_mode;
|
||||
r->result = SAVE_RESULT_OK;
|
||||
r->button_id = SAVE_BUTTON_ID_OK;
|
||||
r->user_data = g_save_user_data;
|
||||
if (r->dir_name != nullptr && g_save_dir_name[0] != '\0') {
|
||||
std::snprintf(static_cast<SaveDataDirName*>(r->dir_name)->data,
|
||||
sizeof(SaveDataDirName::data), "%s", g_save_dir_name);
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogOpen(const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto* p = static_cast<const SaveDataDialogParam*>(param);
|
||||
if (p != nullptr) {
|
||||
g_save_mode = p->mode;
|
||||
g_save_user_data = p->user_data;
|
||||
g_save_dir_name[0] = '\0';
|
||||
LOGF("\t size = %d\n"
|
||||
"\t mode = %d\n"
|
||||
"\t disp_type = %d\n"
|
||||
"\t items = 0x%016" PRIx64 "\n"
|
||||
"\t user_msg_param = 0x%016" PRIx64 "\n"
|
||||
"\t sys_msg_param = 0x%016" PRIx64 "\n"
|
||||
"\t prog_bar_param = 0x%016" PRIx64 "\n"
|
||||
"\t user_data = 0x%016" PRIx64 "\n",
|
||||
p->size, p->mode, p->disp_type, reinterpret_cast<uint64_t>(p->items),
|
||||
reinterpret_cast<uint64_t>(p->user_msg_param),
|
||||
reinterpret_cast<uint64_t>(p->sys_msg_param),
|
||||
reinterpret_cast<uint64_t>(p->prog_bar_param),
|
||||
reinterpret_cast<uint64_t>(p->user_data));
|
||||
|
||||
const auto* items = static_cast<const SaveDataDialogItems*>(p->items);
|
||||
if (items != nullptr && items->dir_names != nullptr) {
|
||||
for (uint32_t i = 0; i < items->dir_names_num; i++) {
|
||||
const auto* name = items->dir_names[i].data;
|
||||
if (name[0] != '\0') {
|
||||
std::snprintf(g_save_dir_name, sizeof(g_save_dir_name), "%s", name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_save_status = SAVE_STATUS_FINISHED;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogClose(const void* close_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t close_param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(close_param));
|
||||
|
||||
g_save_status = SAVE_STATUS_FINISHED;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogIsReadyToDisplay() {
|
||||
PRINT_NAME();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogTerminate() {
|
||||
PRINT_NAME();
|
||||
|
||||
g_save_status = SAVE_STATUS_NONE;
|
||||
g_save_mode = 0;
|
||||
g_save_user_data = nullptr;
|
||||
g_save_dir_name[0] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogProgressBarInc(int target, uint32_t delta) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t target = %d\n"
|
||||
"\t delta = %u\n",
|
||||
target, delta);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogProgressBarSetValue(int target, uint32_t rate) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t target = %d\n"
|
||||
"\t rate = %u\n",
|
||||
target, rate);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace SaveDataDialog
|
||||
|
||||
namespace MsgDialog {
|
||||
|
||||
LIB_NAME("MsgDialog.native", "MsgDialog");
|
||||
|
||||
constexpr int STATUS_NONE = 0;
|
||||
constexpr int STATUS_INITIALIZED = 1;
|
||||
constexpr int STATUS_FINISHED = 3;
|
||||
constexpr int RESULT_OK = 0;
|
||||
constexpr int BUTTON_ID_OK = 1;
|
||||
|
||||
struct MsgDialogParam {
|
||||
uint8_t base_param[48];
|
||||
uint64_t size;
|
||||
int32_t mode;
|
||||
uint32_t pad0;
|
||||
void* user_msg_param;
|
||||
void* prog_bar_param;
|
||||
void* sys_msg_param;
|
||||
int32_t user_id;
|
||||
uint8_t reserved[40];
|
||||
uint32_t pad1;
|
||||
};
|
||||
|
||||
struct MsgDialogResult {
|
||||
int32_t mode;
|
||||
int32_t result;
|
||||
int32_t button_id;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
static int g_status = STATUS_NONE;
|
||||
static int g_mode = 0;
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogInitialize() {
|
||||
PRINT_NAME();
|
||||
|
||||
g_status = STATUS_INITIALIZED;
|
||||
g_mode = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogOpen(const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto* p = static_cast<const MsgDialogParam*>(param);
|
||||
if (p != nullptr) {
|
||||
g_mode = p->mode;
|
||||
LOGF("\t size = 0x%016" PRIx64 "\n"
|
||||
"\t mode = %d\n"
|
||||
"\t user_msg_param = 0x%016" PRIx64 "\n"
|
||||
"\t prog_bar_param = 0x%016" PRIx64 "\n"
|
||||
"\t sys_msg_param = 0x%016" PRIx64 "\n"
|
||||
"\t user_id = %d\n",
|
||||
p->size, p->mode, reinterpret_cast<uint64_t>(p->user_msg_param),
|
||||
reinterpret_cast<uint64_t>(p->prog_bar_param),
|
||||
reinterpret_cast<uint64_t>(p->sys_msg_param), p->user_id);
|
||||
}
|
||||
|
||||
g_status = STATUS_FINISHED;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogUpdateStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
return g_status;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogGetStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
return g_status;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogGetResult(void* result) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (result != nullptr) {
|
||||
auto* r = static_cast<MsgDialogResult*>(result);
|
||||
r->mode = g_mode;
|
||||
r->result = RESULT_OK;
|
||||
r->button_id = BUTTON_ID_OK;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogTerminate() {
|
||||
PRINT_NAME();
|
||||
|
||||
g_status = STATUS_NONE;
|
||||
g_mode = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogClose() {
|
||||
PRINT_NAME();
|
||||
|
||||
g_status = STATUS_FINISHED;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogProgressBarInc(int target, uint32_t delta) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t target = %d\n"
|
||||
"\t delta = %u\n",
|
||||
target, delta);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogProgressBarSetValue(int target, uint32_t rate) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t target = %d\n"
|
||||
"\t rate = %u\n",
|
||||
target, rate);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogProgressBarSetMsg(int target, const char* msg) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t target = %d\n"
|
||||
"\t msg = 0x%016" PRIx64 "\n",
|
||||
target, reinterpret_cast<uint64_t>(msg));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace MsgDialog
|
||||
|
||||
namespace ErrorDialog {
|
||||
|
||||
LIB_NAME("ErrorDialog", "ErrorDialog");
|
||||
|
||||
constexpr int STATUS_NONE = 0;
|
||||
constexpr int STATUS_INITIALIZED = 1;
|
||||
constexpr int STATUS_RUNNING = 2;
|
||||
constexpr int STATUS_FINISHED = 3;
|
||||
|
||||
constexpr int ERROR_NOT_INITIALIZED = static_cast<int>(0x80ed0001);
|
||||
constexpr int ERROR_ALREADY_INITIALIZED = static_cast<int>(0x80ed0002);
|
||||
constexpr int ERROR_PARAM_INVALID = static_cast<int>(0x80ed0003);
|
||||
constexpr int ERROR_INVALID_STATE = static_cast<int>(0x80ed0005);
|
||||
|
||||
struct ErrorDialogParam {
|
||||
int32_t size;
|
||||
int32_t error_code;
|
||||
int32_t user_id;
|
||||
int32_t reserved;
|
||||
};
|
||||
|
||||
static int g_error_status = STATUS_NONE;
|
||||
|
||||
int KYTY_SYSV_ABI ErrorDialogInitialize() {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_error_status != STATUS_NONE) {
|
||||
return ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
g_error_status = STATUS_INITIALIZED;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI ErrorDialogOpen(const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_error_status != STATUS_INITIALIZED && g_error_status != STATUS_FINISHED) {
|
||||
return ERROR_INVALID_STATE;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return ERROR_PARAM_INVALID;
|
||||
}
|
||||
|
||||
const auto* p = static_cast<const ErrorDialogParam*>(param);
|
||||
if (p->size != sizeof(ErrorDialogParam)) {
|
||||
return ERROR_PARAM_INVALID;
|
||||
}
|
||||
|
||||
LOGF("\t size = %d\n"
|
||||
"\t error_code = 0x%08" PRIx32 "\n"
|
||||
"\t user_id = %d\n",
|
||||
p->size, static_cast<uint32_t>(p->error_code), p->user_id);
|
||||
|
||||
g_error_status = STATUS_RUNNING;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI ErrorDialogClose() {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_error_status != STATUS_RUNNING) {
|
||||
return ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
g_error_status = STATUS_FINISHED;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI ErrorDialogTerminate() {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_error_status == STATUS_NONE) {
|
||||
return ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
g_error_status = STATUS_NONE;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI ErrorDialogUpdateStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
if (g_error_status == STATUS_RUNNING) {
|
||||
g_error_status = STATUS_FINISHED;
|
||||
}
|
||||
|
||||
return g_error_status;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI ErrorDialogGetStatus() {
|
||||
PRINT_NAME();
|
||||
|
||||
return g_error_status;
|
||||
}
|
||||
|
||||
} // namespace ErrorDialog
|
||||
|
||||
} // namespace Libs::Dialog
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_DIALOG_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_DIALOG_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
|
||||
namespace Libs::Dialog {
|
||||
|
||||
namespace CommonDialog {
|
||||
|
||||
int KYTY_SYSV_ABI CommonDialogInitialize();
|
||||
|
||||
} // namespace CommonDialog
|
||||
|
||||
namespace ImeDialog {
|
||||
|
||||
int KYTY_SYSV_ABI ImeDialogGetStatus();
|
||||
|
||||
} // namespace ImeDialog
|
||||
|
||||
namespace LoginDialog {
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogInitialize();
|
||||
int KYTY_SYSV_ABI LoginDialogTerminate();
|
||||
int KYTY_SYSV_ABI LoginDialogOpen(const void* param);
|
||||
int KYTY_SYSV_ABI LoginDialogClose();
|
||||
int KYTY_SYSV_ABI LoginDialogUpdateStatus();
|
||||
int KYTY_SYSV_ABI LoginDialogGetStatus();
|
||||
int KYTY_SYSV_ABI LoginDialogGetResult(void* result);
|
||||
void KYTY_SYSV_ABI LoginDialogParamInitialize(void* param);
|
||||
|
||||
} // namespace LoginDialog
|
||||
|
||||
namespace SaveDataDialog {
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDialogInitialize();
|
||||
int KYTY_SYSV_ABI SaveDataDialogGetStatus();
|
||||
int KYTY_SYSV_ABI SaveDataDialogUpdateStatus();
|
||||
int KYTY_SYSV_ABI SaveDataDialogGetResult(void* result);
|
||||
int KYTY_SYSV_ABI SaveDataDialogOpen(const void* param);
|
||||
int KYTY_SYSV_ABI SaveDataDialogClose(const void* close_param);
|
||||
int KYTY_SYSV_ABI SaveDataDialogIsReadyToDisplay();
|
||||
int KYTY_SYSV_ABI SaveDataDialogTerminate();
|
||||
int KYTY_SYSV_ABI SaveDataDialogProgressBarInc(int target, uint32_t delta);
|
||||
int KYTY_SYSV_ABI SaveDataDialogProgressBarSetValue(int target, uint32_t rate);
|
||||
|
||||
} // namespace SaveDataDialog
|
||||
|
||||
namespace MsgDialog {
|
||||
|
||||
int KYTY_SYSV_ABI MsgDialogInitialize();
|
||||
int KYTY_SYSV_ABI MsgDialogOpen(const void* param);
|
||||
int KYTY_SYSV_ABI MsgDialogUpdateStatus();
|
||||
int KYTY_SYSV_ABI MsgDialogGetStatus();
|
||||
int KYTY_SYSV_ABI MsgDialogGetResult(void* result);
|
||||
int KYTY_SYSV_ABI MsgDialogTerminate();
|
||||
int KYTY_SYSV_ABI MsgDialogClose();
|
||||
int KYTY_SYSV_ABI MsgDialogProgressBarInc(int target, uint32_t delta);
|
||||
int KYTY_SYSV_ABI MsgDialogProgressBarSetValue(int target, uint32_t rate);
|
||||
int KYTY_SYSV_ABI MsgDialogProgressBarSetMsg(int target, const char* msg);
|
||||
|
||||
} // namespace MsgDialog
|
||||
|
||||
namespace ErrorDialog {
|
||||
|
||||
int KYTY_SYSV_ABI ErrorDialogInitialize();
|
||||
int KYTY_SYSV_ABI ErrorDialogOpen(const void* param);
|
||||
int KYTY_SYSV_ABI ErrorDialogClose();
|
||||
int KYTY_SYSV_ABI ErrorDialogTerminate();
|
||||
int KYTY_SYSV_ABI ErrorDialogUpdateStatus();
|
||||
int KYTY_SYSV_ABI ErrorDialogGetStatus();
|
||||
|
||||
} // namespace ErrorDialog
|
||||
|
||||
} // namespace Libs::Dialog
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_DIALOG_H_ */
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "libs/errno.h"
|
||||
|
||||
namespace Libs::Posix {
|
||||
|
||||
static thread_local int g_errno = 0;
|
||||
|
||||
KYTY_SYSV_ABI int* GetErrorAddr() {
|
||||
return &g_errno;
|
||||
}
|
||||
|
||||
} // namespace Libs::Posix
|
||||
@@ -0,0 +1,666 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_ERRNO_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_ERRNO_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
|
||||
constexpr int OK = 0;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define POSIX_CALL(func) \
|
||||
[&]() { \
|
||||
auto result = func; \
|
||||
if (result != OK) { \
|
||||
*Posix::GetErrorAddr() = LibKernel::KernelToPosix(result); \
|
||||
return -1; \
|
||||
} \
|
||||
return 0; \
|
||||
}()
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define POSIX_N_CALL(func) \
|
||||
[&]() { \
|
||||
auto result = func; \
|
||||
if (result < 0) { \
|
||||
*Posix::GetErrorAddr() = LibKernel::KernelToPosix(static_cast<int>(result)); \
|
||||
return static_cast<decltype(result)>(-1); \
|
||||
} \
|
||||
return result; \
|
||||
}()
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define POSIX_PTHREAD_CALL(func) \
|
||||
[&]() { \
|
||||
auto result = func; \
|
||||
if (result != OK) { \
|
||||
return LibKernel::KernelToPosix(result); \
|
||||
} \
|
||||
return 0; \
|
||||
}()
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define POSIX_NET_CALL(func) \
|
||||
[&]() { \
|
||||
auto result = func; \
|
||||
if (result != OK) { \
|
||||
*Posix::GetErrorAddr() = Network::NetToPosix(result); \
|
||||
return -1; \
|
||||
} \
|
||||
return 0; \
|
||||
}()
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace Posix {
|
||||
|
||||
KYTY_SYSV_ABI int* GetErrorAddr();
|
||||
|
||||
constexpr int POSIX_EPERM = 1;
|
||||
constexpr int POSIX_ENOENT = 2;
|
||||
constexpr int POSIX_ESRCH = 3;
|
||||
constexpr int POSIX_EINTR = 4;
|
||||
constexpr int POSIX_EIO = 5;
|
||||
constexpr int POSIX_ENXIO = 6;
|
||||
constexpr int POSIX_E2BIG = 7;
|
||||
constexpr int POSIX_ENOEXEC = 8;
|
||||
constexpr int POSIX_EBADF = 9;
|
||||
constexpr int POSIX_ECHILD = 10;
|
||||
constexpr int POSIX_EDEADLK = 11;
|
||||
constexpr int POSIX_ENOMEM = 12;
|
||||
constexpr int POSIX_EACCES = 13;
|
||||
constexpr int POSIX_EFAULT = 14;
|
||||
constexpr int POSIX_ENOTBLK = 15;
|
||||
constexpr int POSIX_EBUSY = 16;
|
||||
constexpr int POSIX_EEXIST = 17;
|
||||
constexpr int POSIX_EXDEV = 18;
|
||||
constexpr int POSIX_ENODEV = 19;
|
||||
constexpr int POSIX_ENOTDIR = 20;
|
||||
constexpr int POSIX_EISDIR = 21;
|
||||
constexpr int POSIX_EINVAL = 22;
|
||||
constexpr int POSIX_ENFILE = 23;
|
||||
constexpr int POSIX_EMFILE = 24;
|
||||
constexpr int POSIX_ENOTTY = 25;
|
||||
constexpr int POSIX_ETXTBSY = 26;
|
||||
constexpr int POSIX_EFBIG = 27;
|
||||
constexpr int POSIX_ENOSPC = 28;
|
||||
constexpr int POSIX_ESPIPE = 29;
|
||||
constexpr int POSIX_EROFS = 30;
|
||||
constexpr int POSIX_EMLINK = 31;
|
||||
constexpr int POSIX_EPIPE = 32;
|
||||
constexpr int POSIX_EDOM = 33;
|
||||
constexpr int POSIX_ERANGE = 34;
|
||||
constexpr int POSIX_EAGAIN = 35;
|
||||
constexpr int POSIX_EWOULDBLOCK = 35;
|
||||
constexpr int POSIX_EINPROGRESS = 36;
|
||||
constexpr int POSIX_EALREADY = 37;
|
||||
constexpr int POSIX_ENOTSOCK = 38;
|
||||
constexpr int POSIX_EDESTADDRREQ = 39;
|
||||
constexpr int POSIX_EMSGSIZE = 40;
|
||||
constexpr int POSIX_EPROTOTYPE = 41;
|
||||
constexpr int POSIX_ENOPROTOOPT = 42;
|
||||
constexpr int POSIX_EPROTONOSUPPORT = 43;
|
||||
constexpr int POSIX_ESOCKTNOSUPPORT = 44;
|
||||
constexpr int POSIX_EOPNOTSUPP = 45;
|
||||
constexpr int POSIX_ENOTSUP = 45;
|
||||
constexpr int POSIX_EPFNOSUPPORT = 46;
|
||||
constexpr int POSIX_EAFNOSUPPORT = 47;
|
||||
constexpr int POSIX_EADDRINUSE = 48;
|
||||
constexpr int POSIX_EADDRNOTAVAIL = 49;
|
||||
constexpr int POSIX_ENETDOWN = 50;
|
||||
constexpr int POSIX_ENETUNREACH = 51;
|
||||
constexpr int POSIX_ENETRESET = 52;
|
||||
constexpr int POSIX_ECONNABORTED = 53;
|
||||
constexpr int POSIX_ECONNRESET = 54;
|
||||
constexpr int POSIX_ENOBUFS = 55;
|
||||
constexpr int POSIX_EISCONN = 56;
|
||||
constexpr int POSIX_ENOTCONN = 57;
|
||||
constexpr int POSIX_ESHUTDOWN = 58;
|
||||
constexpr int POSIX_ETOOMANYREFS = 59;
|
||||
constexpr int POSIX_ETIMEDOUT = 60;
|
||||
constexpr int POSIX_ECONNREFUSED = 61;
|
||||
constexpr int POSIX_ELOOP = 62;
|
||||
constexpr int POSIX_ENAMETOOLONG = 63;
|
||||
constexpr int POSIX_EHOSTDOWN = 64;
|
||||
constexpr int POSIX_EHOSTUNREACH = 65;
|
||||
constexpr int POSIX_ENOTEMPTY = 66;
|
||||
constexpr int POSIX_EPROCLIM = 67;
|
||||
constexpr int POSIX_EUSERS = 68;
|
||||
constexpr int POSIX_EDQUOT = 69;
|
||||
constexpr int POSIX_ESTALE = 70;
|
||||
constexpr int POSIX_EREMOTE = 71;
|
||||
constexpr int POSIX_EBADRPC = 72;
|
||||
constexpr int POSIX_ERPCMISMATCH = 73;
|
||||
constexpr int POSIX_EPROGUNAVAIL = 74;
|
||||
constexpr int POSIX_EPROGMISMATCH = 75;
|
||||
constexpr int POSIX_EPROCUNAVAIL = 76;
|
||||
constexpr int POSIX_ENOLCK = 77;
|
||||
constexpr int POSIX_ENOSYS = 78;
|
||||
constexpr int POSIX_EFTYPE = 79;
|
||||
constexpr int POSIX_EAUTH = 80;
|
||||
constexpr int POSIX_ENEEDAUTH = 81;
|
||||
constexpr int POSIX_EIDRM = 82;
|
||||
constexpr int POSIX_ENOMSG = 83;
|
||||
constexpr int POSIX_EOVERFLOW = 84;
|
||||
constexpr int POSIX_ECANCELED = 85;
|
||||
constexpr int POSIX_EILSEQ = 86;
|
||||
constexpr int POSIX_ENOATTR = 87;
|
||||
constexpr int POSIX_EDOOFUS = 88;
|
||||
constexpr int POSIX_EBADMSG = 89;
|
||||
constexpr int POSIX_EMULTIHOP = 90;
|
||||
constexpr int POSIX_ENOLINK = 91;
|
||||
constexpr int POSIX_EPROTO = 92;
|
||||
constexpr int POSIX_ENOTCAPABLE = 93;
|
||||
constexpr int POSIX_ECAPMODE = 94;
|
||||
constexpr int POSIX_ENOBLK = 95;
|
||||
constexpr int POSIX_EICV = 96;
|
||||
constexpr int POSIX_ENOPLAYGOENT = 97;
|
||||
constexpr int POSIX_EREVOKE = 98;
|
||||
constexpr int POSIX_ESDKVERSION = 99;
|
||||
constexpr int POSIX_ESTART = 100;
|
||||
constexpr int POSIX_ESTOP = 101;
|
||||
constexpr int POSIX_EINVALID2MB = 102;
|
||||
constexpr int POSIX_ELAST = 102;
|
||||
constexpr int POSIX_EADHOC = 160;
|
||||
constexpr int POSIX_EINACTIVEDISABLED = 163;
|
||||
constexpr int POSIX_ENETNODATA = 164;
|
||||
constexpr int POSIX_ENETDESC = 165;
|
||||
constexpr int POSIX_ENETDESCTIMEDOUT = 166;
|
||||
constexpr int POSIX_ENETINTR = 167;
|
||||
constexpr int POSIX_ERETURN = 205;
|
||||
constexpr int POSIX_EFPOS = 152;
|
||||
constexpr int POSIX_ENODATA = 1040;
|
||||
constexpr int POSIX_ENOSR = 1050;
|
||||
constexpr int POSIX_ENOSTR = 1051;
|
||||
constexpr int POSIX_ENOTRECOVERABLE = 1056;
|
||||
constexpr int POSIX_EOTHER = 1062;
|
||||
constexpr int POSIX_EOWNERDEAD = 1064;
|
||||
constexpr int POSIX_ETIME = 1074;
|
||||
|
||||
} // namespace Posix
|
||||
|
||||
namespace LibKernel {
|
||||
|
||||
inline int KernelToPosix(int kernel_errno) {
|
||||
return kernel_errno > -2147352576 && kernel_errno <= -2147352475 ? kernel_errno + 2147352576
|
||||
: 1062;
|
||||
}
|
||||
|
||||
constexpr int KERNEL_ERROR_UNKNOWN = -2147352576; /* 0x80020000 */
|
||||
constexpr int KERNEL_ERROR_EPERM = -2147352575; /* 0x80020001 */
|
||||
constexpr int KERNEL_ERROR_ENOENT = -2147352574; /* 0x80020002 */
|
||||
constexpr int KERNEL_ERROR_ESRCH = -2147352573; /* 0x80020003 */
|
||||
constexpr int KERNEL_ERROR_EINTR = -2147352572; /* 0x80020004 */
|
||||
constexpr int KERNEL_ERROR_EIO = -2147352571; /* 0x80020005 */
|
||||
constexpr int KERNEL_ERROR_ENXIO = -2147352570; /* 0x80020006 */
|
||||
constexpr int KERNEL_ERROR_E2BIG = -2147352569; /* 0x80020007 */
|
||||
constexpr int KERNEL_ERROR_ENOEXEC = -2147352568; /* 0x80020008 */
|
||||
constexpr int KERNEL_ERROR_EBADF = -2147352567; /* 0x80020009 */
|
||||
constexpr int KERNEL_ERROR_ECHILD = -2147352566; /* 0x8002000A */
|
||||
constexpr int KERNEL_ERROR_EDEADLK = -2147352565; /* 0x8002000B */
|
||||
constexpr int KERNEL_ERROR_ENOMEM = -2147352564; /* 0x8002000C */
|
||||
constexpr int KERNEL_ERROR_EACCES = -2147352563; /* 0x8002000D */
|
||||
constexpr int KERNEL_ERROR_EFAULT = -2147352562; /* 0x8002000E */
|
||||
constexpr int KERNEL_ERROR_ENOTBLK = -2147352561; /* 0x8002000F */
|
||||
constexpr int KERNEL_ERROR_EBUSY = -2147352560; /* 0x80020010 */
|
||||
constexpr int KERNEL_ERROR_EEXIST = -2147352559; /* 0x80020011 */
|
||||
constexpr int KERNEL_ERROR_EXDEV = -2147352558; /* 0x80020012 */
|
||||
constexpr int KERNEL_ERROR_ENODEV = -2147352557; /* 0x80020013 */
|
||||
constexpr int KERNEL_ERROR_ENOTDIR = -2147352556; /* 0x80020014 */
|
||||
constexpr int KERNEL_ERROR_EISDIR = -2147352555; /* 0x80020015 */
|
||||
constexpr int KERNEL_ERROR_EINVAL = -2147352554; /* 0x80020016 */
|
||||
constexpr int KERNEL_ERROR_ENFILE = -2147352553; /* 0x80020017 */
|
||||
constexpr int KERNEL_ERROR_EMFILE = -2147352552; /* 0x80020018 */
|
||||
constexpr int KERNEL_ERROR_ENOTTY = -2147352551; /* 0x80020019 */
|
||||
constexpr int KERNEL_ERROR_ETXTBSY = -2147352550; /* 0x8002001A */
|
||||
constexpr int KERNEL_ERROR_EFBIG = -2147352549; /* 0x8002001B */
|
||||
constexpr int KERNEL_ERROR_ENOSPC = -2147352548; /* 0x8002001C */
|
||||
constexpr int KERNEL_ERROR_ESPIPE = -2147352547; /* 0x8002001D */
|
||||
constexpr int KERNEL_ERROR_EROFS = -2147352546; /* 0x8002001E */
|
||||
constexpr int KERNEL_ERROR_EMLINK = -2147352545; /* 0x8002001F */
|
||||
constexpr int KERNEL_ERROR_EPIPE = -2147352544; /* 0x80020020 */
|
||||
constexpr int KERNEL_ERROR_EDOM = -2147352543; /* 0x80020021 */
|
||||
constexpr int KERNEL_ERROR_ERANGE = -2147352542; /* 0x80020022 */
|
||||
constexpr int KERNEL_ERROR_EAGAIN = -2147352541; /* 0x80020023 */
|
||||
constexpr int KERNEL_ERROR_EWOULDBLOCK = -2147352541; /* 0x80020023 */
|
||||
constexpr int KERNEL_ERROR_EINPROGRESS = -2147352540; /* 0x80020024 */
|
||||
constexpr int KERNEL_ERROR_EALREADY = -2147352539; /* 0x80020025 */
|
||||
constexpr int KERNEL_ERROR_ENOTSOCK = -2147352538; /* 0x80020026 */
|
||||
constexpr int KERNEL_ERROR_EDESTADDRREQ = -2147352537; /* 0x80020027 */
|
||||
constexpr int KERNEL_ERROR_EMSGSIZE = -2147352536; /* 0x80020028 */
|
||||
constexpr int KERNEL_ERROR_EPROTOTYPE = -2147352535; /* 0x80020029 */
|
||||
constexpr int KERNEL_ERROR_ENOPROTOOPT = -2147352534; /* 0x8002002A */
|
||||
constexpr int KERNEL_ERROR_EPROTONOSUPPORT = -2147352533; /* 0x8002002B */
|
||||
constexpr int KERNEL_ERROR_ESOCKTNOSUPPORT = -2147352532; /* 0x8002002C */
|
||||
constexpr int KERNEL_ERROR_EOPNOTSUPP = -2147352531; /* 0x8002002D */
|
||||
constexpr int KERNEL_ERROR_ENOTSUP = -2147352531; /* 0x8002002D */
|
||||
constexpr int KERNEL_ERROR_EPFNOSUPPORT = -2147352530; /* 0x8002002E */
|
||||
constexpr int KERNEL_ERROR_EAFNOSUPPORT = -2147352529; /* 0x8002002F */
|
||||
constexpr int KERNEL_ERROR_EADDRINUSE = -2147352528; /* 0x80020030 */
|
||||
constexpr int KERNEL_ERROR_EADDRNOTAVAIL = -2147352527; /* 0x80020031 */
|
||||
constexpr int KERNEL_ERROR_ENETDOWN = -2147352526; /* 0x80020032 */
|
||||
constexpr int KERNEL_ERROR_ENETUNREACH = -2147352525; /* 0x80020033 */
|
||||
constexpr int KERNEL_ERROR_ENETRESET = -2147352524; /* 0x80020034 */
|
||||
constexpr int KERNEL_ERROR_ECONNABORTED = -2147352523; /* 0x80020035 */
|
||||
constexpr int KERNEL_ERROR_ECONNRESET = -2147352522; /* 0x80020036 */
|
||||
constexpr int KERNEL_ERROR_ENOBUFS = -2147352521; /* 0x80020037 */
|
||||
constexpr int KERNEL_ERROR_EISCONN = -2147352520; /* 0x80020038 */
|
||||
constexpr int KERNEL_ERROR_ENOTCONN = -2147352519; /* 0x80020039 */
|
||||
constexpr int KERNEL_ERROR_ESHUTDOWN = -2147352518; /* 0x8002003A */
|
||||
constexpr int KERNEL_ERROR_ETOOMANYREFS = -2147352517; /* 0x8002003B */
|
||||
constexpr int KERNEL_ERROR_ETIMEDOUT = -2147352516; /* 0x8002003C */
|
||||
constexpr int KERNEL_ERROR_ECONNREFUSED = -2147352515; /* 0x8002003D */
|
||||
constexpr int KERNEL_ERROR_ELOOP = -2147352514; /* 0x8002003E */
|
||||
constexpr int KERNEL_ERROR_ENAMETOOLONG = -2147352513; /* 0x8002003F */
|
||||
constexpr int KERNEL_ERROR_EHOSTDOWN = -2147352512; /* 0x80020040 */
|
||||
constexpr int KERNEL_ERROR_EHOSTUNREACH = -2147352511; /* 0x80020041 */
|
||||
constexpr int KERNEL_ERROR_ENOTEMPTY = -2147352510; /* 0x80020042 */
|
||||
constexpr int KERNEL_ERROR_EPROCLIM = -2147352509; /* 0x80020043 */
|
||||
constexpr int KERNEL_ERROR_EUSERS = -2147352508; /* 0x80020044 */
|
||||
constexpr int KERNEL_ERROR_EDQUOT = -2147352507; /* 0x80020045 */
|
||||
constexpr int KERNEL_ERROR_ESTALE = -2147352506; /* 0x80020046 */
|
||||
constexpr int KERNEL_ERROR_EREMOTE = -2147352505; /* 0x80020047 */
|
||||
constexpr int KERNEL_ERROR_EBADRPC = -2147352504; /* 0x80020048 */
|
||||
constexpr int KERNEL_ERROR_ERPCMISMATCH = -2147352503; /* 0x80020049 */
|
||||
constexpr int KERNEL_ERROR_EPROGUNAVAIL = -2147352502; /* 0x8002004A */
|
||||
constexpr int KERNEL_ERROR_EPROGMISMATCH = -2147352501; /* 0x8002004B */
|
||||
constexpr int KERNEL_ERROR_EPROCUNAVAIL = -2147352500; /* 0x8002004C */
|
||||
constexpr int KERNEL_ERROR_ENOLCK = -2147352499; /* 0x8002004D */
|
||||
constexpr int KERNEL_ERROR_ENOSYS = -2147352498; /* 0x8002004E */
|
||||
constexpr int KERNEL_ERROR_EFTYPE = -2147352497; /* 0x8002004F */
|
||||
constexpr int KERNEL_ERROR_EAUTH = -2147352496; /* 0x80020050 */
|
||||
constexpr int KERNEL_ERROR_ENEEDAUTH = -2147352495; /* 0x80020051 */
|
||||
constexpr int KERNEL_ERROR_EIDRM = -2147352494; /* 0x80020052 */
|
||||
constexpr int KERNEL_ERROR_ENOMSG = -2147352493; /* 0x80020053 */
|
||||
constexpr int KERNEL_ERROR_EOVERFLOW = -2147352492; /* 0x80020054 */
|
||||
constexpr int KERNEL_ERROR_ECANCELED = -2147352491; /* 0x80020055 */
|
||||
constexpr int KERNEL_ERROR_EILSEQ = -2147352490; /* 0x80020056 */
|
||||
constexpr int KERNEL_ERROR_ENOATTR = -2147352489; /* 0x80020057 */
|
||||
constexpr int KERNEL_ERROR_EDOOFUS = -2147352488; /* 0x80020058 */
|
||||
constexpr int KERNEL_ERROR_EBADMSG = -2147352487; /* 0x80020059 */
|
||||
constexpr int KERNEL_ERROR_EMULTIHOP = -2147352486; /* 0x8002005A */
|
||||
constexpr int KERNEL_ERROR_ENOLINK = -2147352485; /* 0x8002005B */
|
||||
constexpr int KERNEL_ERROR_EPROTO = -2147352484; /* 0x8002005C */
|
||||
constexpr int KERNEL_ERROR_ENOTCAPABLE = -2147352483; /* 0x8002005D */
|
||||
constexpr int KERNEL_ERROR_ECAPMODE = -2147352482; /* 0x8002005E */
|
||||
constexpr int KERNEL_ERROR_ENOBLK = -2147352481; /* 0x8002005F */
|
||||
constexpr int KERNEL_ERROR_EICV = -2147352480; /* 0x80020060 */
|
||||
constexpr int KERNEL_ERROR_ENOPLAYGOENT = -2147352479; /* 0x80020061 */
|
||||
constexpr int KERNEL_ERROR_EREVOKE = -2147352478; /* 0x80020062 */
|
||||
constexpr int KERNEL_ERROR_ESDKVERSION = -2147352477; /* 0x80020063 */
|
||||
constexpr int KERNEL_ERROR_ESTART = -2147352476; /* 0x80020064 */
|
||||
constexpr int KERNEL_ERROR_ESTOP = -2147352475; /* 0x80020065 */
|
||||
|
||||
} // namespace LibKernel
|
||||
|
||||
namespace VideoOut {
|
||||
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_VALUE = -2144796671; /* 0x80290001 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_ADDRESS = -2144796670; /* 0x80290002 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_PIXEL_FORMAT = -2144796669; /* 0x80290003 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_PITCH = -2144796668; /* 0x80290004 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_RESOLUTION = -2144796667; /* 0x80290005 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_FLIP_MODE = -2144796666; /* 0x80290006 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_TILING_MODE = -2144796665; /* 0x80290007 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_ASPECT_RATIO = -2144796664; /* 0x80290008 */
|
||||
constexpr int VIDEO_OUT_ERROR_RESOURCE_BUSY = -2144796663; /* 0x80290009 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_INDEX = -2144796662; /* 0x8029000A */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_HANDLE = -2144796661; /* 0x8029000B */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE = -2144796660; /* 0x8029000C */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_EVENT = -2144796659; /* 0x8029000D */
|
||||
constexpr int VIDEO_OUT_ERROR_NO_EMPTY_SLOT = -2144796657; /* 0x8029000F */
|
||||
constexpr int VIDEO_OUT_ERROR_SLOT_OCCUPIED = -2144796656; /* 0x80290010 */
|
||||
constexpr int VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = -2144796654; /* 0x80290012 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_MEMORY = -2144796653; /* 0x80290013 */
|
||||
constexpr int VIDEO_OUT_ERROR_MEMORY_NOT_PHYSICALLY_CONTIGUOUS = -2144796652; /* 0x80290014 */
|
||||
constexpr int VIDEO_OUT_ERROR_MEMORY_INVALID_ALIGNMENT = -2144796651; /* 0x80290015 */
|
||||
constexpr int VIDEO_OUT_ERROR_UNSUPPORTED_OUTPUT_MODE = -2144796650; /* 0x80290016 */
|
||||
constexpr int VIDEO_OUT_ERROR_OVERFLOW = -2144796649; /* 0x80290017 */
|
||||
constexpr int VIDEO_OUT_ERROR_NO_DEVICE = -2144796648; /* 0x80290018 */
|
||||
constexpr int VIDEO_OUT_ERROR_UNAVAILABLE_OUTPUT_MODE = -2144796647; /* 0x80290019 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_OPTION = -2144796646; /* 0x8029001A */
|
||||
constexpr int VIDEO_OUT_ERROR_PORT_UNSUPPORTED_FUNCTION = -2144796645; /* 0x8029001B */
|
||||
constexpr int VIDEO_OUT_ERROR_UNSUPPORTED_OPERATION = -2144796644; /* 0x8029001C */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_CATEGORY = -2144796643; /* 0x8029001D */
|
||||
constexpr int VIDEO_OUT_ERROR_FATAL = -2144796417; /* 0x802900FF */
|
||||
constexpr int VIDEO_OUT_ERROR_UNKNOWN = -2144796418; /* 0x802900FE */
|
||||
constexpr int VIDEO_OUT_ERROR_ENOMEM = -2144792564; /* 0x8029100C */
|
||||
|
||||
} // namespace VideoOut
|
||||
|
||||
namespace Audio {
|
||||
|
||||
constexpr int AUDIO_OUT_ERROR_NOT_OPENED = -2144993279; /* 0x80260001 */
|
||||
constexpr int AUDIO_OUT_ERROR_BUSY = -2144993278; /* 0x80260002 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_PORT = -2144993277; /* 0x80260003 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_POINTER = -2144993276; /* 0x80260004 */
|
||||
constexpr int AUDIO_OUT_ERROR_PORT_FULL = -2144993275; /* 0x80260005 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_SIZE = -2144993274; /* 0x80260006 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_FORMAT = -2144993273; /* 0x80260007 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_SAMPLE_FREQ = -2144993272; /* 0x80260008 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_VOLUME = -2144993271; /* 0x80260009 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_PORT_TYPE = -2144993270; /* 0x8026000A */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_CONF_TYPE = -2144993268; /* 0x8026000C */
|
||||
constexpr int AUDIO_OUT_ERROR_OUT_OF_MEMORY = -2144993267; /* 0x8026000D */
|
||||
constexpr int AUDIO_OUT_ERROR_ALREADY_INIT = -2144993266; /* 0x8026000E */
|
||||
constexpr int AUDIO_OUT_ERROR_NOT_INIT = -2144993265; /* 0x8026000F */
|
||||
constexpr int AUDIO_OUT_ERROR_MEMORY = -2144993264; /* 0x80260010 */
|
||||
constexpr int AUDIO_OUT_ERROR_SYSTEM_RESOURCE = -2144993263; /* 0x80260011 */
|
||||
constexpr int AUDIO_OUT_ERROR_TRANS_EVENT = -2144993262; /* 0x80260012 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_FLAG = -2144993261; /* 0x80260013 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_MIXLEVEL = -2144993260; /* 0x80260014 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_ARG = -2144993259; /* 0x80260015 */
|
||||
constexpr int AUDIO_OUT_ERROR_INVALID_PARAM = -2144993258; /* 0x80260016 */
|
||||
|
||||
constexpr int AUDIO_IN_ERROR_FATAL = -2144993024; /* 0x80260100 */
|
||||
constexpr int AUDIO_IN_ERROR_INVALID_HANDLE = -2144993023; /* 0x80260101 */
|
||||
constexpr int AUDIO_IN_ERROR_INVALID_SIZE = -2144993022; /* 0x80260102 */
|
||||
constexpr int AUDIO_IN_ERROR_INVALID_FREQ = -2144993021; /* 0x80260103 */
|
||||
constexpr int AUDIO_IN_ERROR_INVALID_TYPE = -2144993020; /* 0x80260104 */
|
||||
constexpr int AUDIO_IN_ERROR_INVALID_POINTER = -2144993019; /* 0x80260105 */
|
||||
constexpr int AUDIO_IN_ERROR_INVALID_PARAM = -2144993018; /* 0x80260106 */
|
||||
constexpr int AUDIO_IN_ERROR_PORT_FULL = -2144993017; /* 0x80260107 */
|
||||
constexpr int AUDIO_IN_ERROR_OUT_OF_MEMORY = -2144993016; /* 0x80260108 */
|
||||
constexpr int AUDIO_IN_ERROR_NOT_OPENED = -2144993015; /* 0x80260109 */
|
||||
constexpr int AUDIO_IN_ERROR_BUSY = -2144993014; /* 0x8026010A */
|
||||
constexpr int AUDIO_IN_ERROR_SYSTEM_MEMORY = -2144993013; /* 0x8026010B */
|
||||
constexpr int AUDIO_IN_ERROR_SYSTEM_IPC = -2144993012; /* 0x8026010C */
|
||||
|
||||
} // namespace Audio
|
||||
|
||||
namespace SystemService {
|
||||
|
||||
constexpr int SYSTEM_SERVICE_ERROR_INTERNAL = -2136932351; /* 0x80A10001 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_UNAVAILABLE = -2136932350; /* 0x80A10002 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_PARAMETER = -2136932349; /* 0x80A10003 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_NO_EVENT = -2136932348; /* 0x80A10004 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_REJECTED = -2136932347; /* 0x80A10005 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_NEED_DISPLAY_SAFE_AREA_SETTINGS = -2136932346; /* 0x80A10006 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_INVALID_URI_LEN = -2136932345; /* 0x80A10007 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_INVALID_URI_SCHEME = -2136932344; /* 0x80A10008 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_NO_APP_INFO = -2136932343; /* 0x80A10009 */
|
||||
constexpr int SYSTEM_SERVICE_ERROR_NOT_FLAG_IN_PARAM_SFO = -2136932342; /* 0x80A1000A */
|
||||
|
||||
} // namespace SystemService
|
||||
|
||||
namespace Network {
|
||||
|
||||
inline int NetToPosix(int kernel_errno) {
|
||||
return kernel_errno > -2143223551 && kernel_errno <= -2143223316 ? kernel_errno + 2143223551 + 1
|
||||
: 204;
|
||||
}
|
||||
|
||||
constexpr int NET_ERROR_EPERM = -2143223551; /* 0x80410101 */
|
||||
constexpr int NET_ERROR_ENOENT = -2143223550; /* 0x80410102 */
|
||||
constexpr int NET_ERROR_ESRCH = -2143223549; /* 0x80410103 */
|
||||
constexpr int NET_ERROR_EINTR = -2143223548; /* 0x80410104 */
|
||||
constexpr int NET_ERROR_EIO = -2143223547; /* 0x80410105 */
|
||||
constexpr int NET_ERROR_ENXIO = -2143223546; /* 0x80410106 */
|
||||
constexpr int NET_ERROR_E2BIG = -2143223545; /* 0x80410107 */
|
||||
constexpr int NET_ERROR_ENOEXEC = -2143223544; /* 0x80410108 */
|
||||
constexpr int NET_ERROR_EBADF = -2143223543; /* 0x80410109 */
|
||||
constexpr int NET_ERROR_ECHILD = -2143223542; /* 0x8041010A */
|
||||
constexpr int NET_ERROR_EDEADLK = -2143223541; /* 0x8041010B */
|
||||
constexpr int NET_ERROR_ENOMEM = -2143223540; /* 0x8041010C */
|
||||
constexpr int NET_ERROR_EACCES = -2143223539; /* 0x8041010D */
|
||||
constexpr int NET_ERROR_EFAULT = -2143223538; /* 0x8041010E */
|
||||
constexpr int NET_ERROR_ENOTBLK = -2143223537; /* 0x8041010F */
|
||||
constexpr int NET_ERROR_EBUSY = -2143223536; /* 0x80410110 */
|
||||
constexpr int NET_ERROR_EEXIST = -2143223535; /* 0x80410111 */
|
||||
constexpr int NET_ERROR_EXDEV = -2143223534; /* 0x80410112 */
|
||||
constexpr int NET_ERROR_ENODEV = -2143223533; /* 0x80410113 */
|
||||
constexpr int NET_ERROR_ENOTDIR = -2143223532; /* 0x80410114 */
|
||||
constexpr int NET_ERROR_EISDIR = -2143223531; /* 0x80410115 */
|
||||
constexpr int NET_ERROR_EINVAL = -2143223530; /* 0x80410116 */
|
||||
constexpr int NET_ERROR_ENFILE = -2143223529; /* 0x80410117 */
|
||||
constexpr int NET_ERROR_EMFILE = -2143223528; /* 0x80410118 */
|
||||
constexpr int NET_ERROR_ENOTTY = -2143223527; /* 0x80410119 */
|
||||
constexpr int NET_ERROR_ETXTBSY = -2143223526; /* 0x8041011A */
|
||||
constexpr int NET_ERROR_EFBIG = -2143223525; /* 0x8041011B */
|
||||
constexpr int NET_ERROR_ENOSPC = -2143223524; /* 0x8041011C */
|
||||
constexpr int NET_ERROR_ESPIPE = -2143223523; /* 0x8041011D */
|
||||
constexpr int NET_ERROR_EROFS = -2143223522; /* 0x8041011E */
|
||||
constexpr int NET_ERROR_EMLINK = -2143223521; /* 0x8041011F */
|
||||
constexpr int NET_ERROR_EPIPE = -2143223520; /* 0x80410120 */
|
||||
constexpr int NET_ERROR_EDOM = -2143223519; /* 0x80410121 */
|
||||
constexpr int NET_ERROR_ERANGE = -2143223518; /* 0x80410122 */
|
||||
constexpr int NET_ERROR_EAGAIN = -2143223517; /* 0x80410123 */
|
||||
constexpr int NET_ERROR_EWOULDBLOCK = -2143223517; /* 0x80410123 */
|
||||
constexpr int NET_ERROR_EINPROGRESS = -2143223516; /* 0x80410124 */
|
||||
constexpr int NET_ERROR_EALREADY = -2143223515; /* 0x80410125 */
|
||||
constexpr int NET_ERROR_ENOTSOCK = -2143223514; /* 0x80410126 */
|
||||
constexpr int NET_ERROR_EDESTADDRREQ = -2143223513; /* 0x80410127 */
|
||||
constexpr int NET_ERROR_EMSGSIZE = -2143223512; /* 0x80410128 */
|
||||
constexpr int NET_ERROR_EPROTOTYPE = -2143223511; /* 0x80410129 */
|
||||
constexpr int NET_ERROR_ENOPROTOOPT = -2143223510; /* 0x8041012A */
|
||||
constexpr int NET_ERROR_EPROTONOSUPPORT = -2143223509; /* 0x8041012B */
|
||||
constexpr int NET_ERROR_ESOCKTNOSUPPORT = -2143223508; /* 0x8041012C */
|
||||
constexpr int NET_ERROR_EOPNOTSUPP = -2143223507; /* 0x8041012D */
|
||||
constexpr int NET_ERROR_ENOTSUP = -2143223507; /* 0x8041012D */
|
||||
constexpr int NET_ERROR_EPFNOSUPPORT = -2143223506; /* 0x8041012E */
|
||||
constexpr int NET_ERROR_EAFNOSUPPORT = -2143223505; /* 0x8041012F */
|
||||
constexpr int NET_ERROR_EADDRINUSE = -2143223504; /* 0x80410130 */
|
||||
constexpr int NET_ERROR_EADDRNOTAVAIL = -2143223503; /* 0x80410131 */
|
||||
constexpr int NET_ERROR_ENETDOWN = -2143223502; /* 0x80410132 */
|
||||
constexpr int NET_ERROR_ENETUNREACH = -2143223501; /* 0x80410133 */
|
||||
constexpr int NET_ERROR_ENETRESET = -2143223500; /* 0x80410134 */
|
||||
constexpr int NET_ERROR_ECONNABORTED = -2143223499; /* 0x80410135 */
|
||||
constexpr int NET_ERROR_ECONNRESET = -2143223498; /* 0x80410136 */
|
||||
constexpr int NET_ERROR_ENOBUFS = -2143223497; /* 0x80410137 */
|
||||
constexpr int NET_ERROR_EISCONN = -2143223496; /* 0x80410138 */
|
||||
constexpr int NET_ERROR_ENOTCONN = -2143223495; /* 0x80410139 */
|
||||
constexpr int NET_ERROR_ESHUTDOWN = -2143223494; /* 0x8041013A */
|
||||
constexpr int NET_ERROR_ETOOMANYREFS = -2143223493; /* 0x8041013B */
|
||||
constexpr int NET_ERROR_ETIMEDOUT = -2143223492; /* 0x8041013C */
|
||||
constexpr int NET_ERROR_ECONNREFUSED = -2143223491; /* 0x8041013D */
|
||||
constexpr int NET_ERROR_ELOOP = -2143223490; /* 0x8041013E */
|
||||
constexpr int NET_ERROR_ENAMETOOLONG = -2143223489; /* 0x8041013F */
|
||||
constexpr int NET_ERROR_EHOSTDOWN = -2143223488; /* 0x80410140 */
|
||||
constexpr int NET_ERROR_EHOSTUNREACH = -2143223487; /* 0x80410141 */
|
||||
constexpr int NET_ERROR_ENOTEMPTY = -2143223486; /* 0x80410142 */
|
||||
constexpr int NET_ERROR_EPROCLIM = -2143223485; /* 0x80410143 */
|
||||
constexpr int NET_ERROR_EUSERS = -2143223484; /* 0x80410144 */
|
||||
constexpr int NET_ERROR_EDQUOT = -2143223483; /* 0x80410145 */
|
||||
constexpr int NET_ERROR_ESTALE = -2143223482; /* 0x80410146 */
|
||||
constexpr int NET_ERROR_EREMOTE = -2143223481; /* 0x80410147 */
|
||||
constexpr int NET_ERROR_EBADRPC = -2143223480; /* 0x80410148 */
|
||||
constexpr int NET_ERROR_ERPCMISMATCH = -2143223479; /* 0x80410149 */
|
||||
constexpr int NET_ERROR_EPROGUNAVAIL = -2143223478; /* 0x8041014A */
|
||||
constexpr int NET_ERROR_EPROGMISMATCH = -2143223477; /* 0x8041014B */
|
||||
constexpr int NET_ERROR_EPROCUNAVAIL = -2143223476; /* 0x8041014C */
|
||||
constexpr int NET_ERROR_ENOLCK = -2143223475; /* 0x8041014D */
|
||||
constexpr int NET_ERROR_ENOSYS = -2143223474; /* 0x8041014E */
|
||||
constexpr int NET_ERROR_EFTYPE = -2143223473; /* 0x8041014F */
|
||||
constexpr int NET_ERROR_EAUTH = -2143223472; /* 0x80410150 */
|
||||
constexpr int NET_ERROR_ENEEDAUTH = -2143223471; /* 0x80410151 */
|
||||
constexpr int NET_ERROR_EIDRM = -2143223470; /* 0x80410152 */
|
||||
constexpr int NET_ERROR_ENOMS = -2143223469; /* 0x80410153 */
|
||||
constexpr int NET_ERROR_EOVERFLOW = -2143223468; /* 0x80410154 */
|
||||
constexpr int NET_ERROR_ECANCELED = -2143223467; /* 0x80410155 */
|
||||
constexpr int NET_ERROR_EPROTO = -2143223460; /* 0x8041015C */
|
||||
constexpr int NET_ERROR_EADHOC = -2143223392; /* 0x804101A0 */
|
||||
constexpr int NET_ERROR_ERESERVED161 = -2143223391; /* 0x804101A1 */
|
||||
constexpr int NET_ERROR_ERESERVED162 = -2143223390; /* 0x804101A2 */
|
||||
constexpr int NET_ERROR_EINACTIVEDISABLED = -2143223389; /* 0x804101A3 */
|
||||
constexpr int NET_ERROR_ENODATA = -2143223388; /* 0x804101A4 */
|
||||
constexpr int NET_ERROR_EDESC = -2143223387; /* 0x804101A5 */
|
||||
constexpr int NET_ERROR_EDESCTIMEDOUT = -2143223386; /* 0x804101A6 */
|
||||
constexpr int NET_ERROR_ENETINTR = -2143223385; /* 0x804101A7 */
|
||||
constexpr int NET_ERROR_ENOTINIT = -2143223352; /* 0x804101C8 */
|
||||
constexpr int NET_ERROR_ENOLIBMEM = -2143223351; /* 0x804101C9 */
|
||||
constexpr int NET_ERROR_ERESERVED202 = -2143223350; /* 0x804101CA */
|
||||
constexpr int NET_ERROR_ECALLBACK = -2143223349; /* 0x804101CB */
|
||||
constexpr int NET_ERROR_EINTERNAL = -2143223348; /* 0x804101CC */
|
||||
constexpr int NET_ERROR_ERETURN = -2143223347; /* 0x804101CD */
|
||||
constexpr int NET_ERROR_ENOALLOCMEM = -2143223346; /* 0x804101CE */
|
||||
constexpr int NET_ERROR_RESOLVER_EINTERNAL = -2143223332; /* 0x804101DC */
|
||||
constexpr int NET_ERROR_RESOLVER_EBUSY = -2143223331; /* 0x804101DD */
|
||||
constexpr int NET_ERROR_RESOLVER_ENOSPACE = -2143223330; /* 0x804101DE */
|
||||
constexpr int NET_ERROR_RESOLVER_EPACKET = -2143223329; /* 0x804101DF */
|
||||
constexpr int NET_ERROR_RESOLVER_ERESERVED224 = -2143223328; /* 0x804101E0 */
|
||||
constexpr int NET_ERROR_RESOLVER_ENODNS = -2143223327; /* 0x804101E1 */
|
||||
constexpr int NET_ERROR_RESOLVER_ETIMEDOUT = -2143223326; /* 0x804101E2 */
|
||||
constexpr int NET_ERROR_RESOLVER_ENOSUPPORT = -2143223325; /* 0x804101E3 */
|
||||
constexpr int NET_ERROR_RESOLVER_EFORMAT = -2143223324; /* 0x804101E4 */
|
||||
constexpr int NET_ERROR_RESOLVER_ESERVERFAILURE = -2143223323; /* 0x804101E5 */
|
||||
constexpr int NET_ERROR_RESOLVER_ENOHOST = -2143223322; /* 0x804101E6 */
|
||||
constexpr int NET_ERROR_RESOLVER_ENOTIMPLEMENTED = -2143223321; /* 0x804101E7 */
|
||||
constexpr int NET_ERROR_RESOLVER_ESERVERREFUSED = -2143223320; /* 0x804101E8 */
|
||||
constexpr int NET_ERROR_RESOLVER_ENORECORD = -2143223319; /* 0x804101E9 */
|
||||
constexpr int NET_ERROR_RESOLVER_EALIGNMENT = -2143223318; /* 0x804101EA */
|
||||
constexpr int NET_ERROR_RESOLVER_ENOTFOUND = -2143223317; /* 0x804101EB */
|
||||
constexpr int NET_ERROR_RESOLVER_ENOTINIT = -2143223316; /* 0x804101EC */
|
||||
|
||||
constexpr int SSL_ERROR_BEFORE_INIT = -2137657343; /* 0x8095F001 */
|
||||
constexpr int SSL_ERROR_ALREADY_INITED = -2137657342; /* 0x8095F002 */
|
||||
constexpr int SSL_ERROR_BROKEN = -2137657341; /* 0x8095F003 */
|
||||
constexpr int SSL_ERROR_NOT_FOUND = -2137657340; /* 0x8095F004 */
|
||||
constexpr int SSL_ERROR_INVALID_FORMAT = -2137657339; /* 0x8095F005 */
|
||||
constexpr int SSL_ERROR_INVALID_ID = -2137657338; /* 0x8095F006 */
|
||||
constexpr int SSL_ERROR_INVALID_VALUE = -2137657337; /* 0x8095F007 */
|
||||
constexpr int SSL_ERROR_OUT_OF_SIZE = -2137657336; /* 0x8095F008 */
|
||||
constexpr int SSL_ERROR_INTERNAL = -2137657335; /* 0x8095F009 */
|
||||
constexpr int SSL_ERROR_INVALID_CERT = -2137657334; /* 0x8095F00A */
|
||||
constexpr int SSL_ERROR_CN_CHECK = -2137657333; /* 0x8095F00B */
|
||||
constexpr int SSL_ERROR_UNKNOWN_CA = -2137657332; /* 0x8095F00C */
|
||||
constexpr int SSL_ERROR_NOT_AFTER_CHECK = -2137657331; /* 0x8095F00D */
|
||||
constexpr int SSL_ERROR_NOT_BEFORE_CHECK = -2137657330; /* 0x8095F00E */
|
||||
constexpr int SSL_ERROR_EAGAIN = -2137657329; /* 0x8095F00F */
|
||||
constexpr int SSL_ERROR_FATAL_ALERT = -2137657328; /* 0x8095F010 */
|
||||
constexpr int SSL_ERROR_BUSY = -2137657326; /* 0x8095F012 */
|
||||
constexpr int SSL_ERROR_WANT_POLLIN = -2137657325; /* 0x8095F013 */
|
||||
constexpr int SSL_ERROR_WANT_POLLOUT = -2137657324; /* 0x8095F014 */
|
||||
constexpr int SSL_ERROR_INSUFFICIENT_STACKSIZE = -2137657323; /* 0x8095F015 */
|
||||
constexpr int SSL_ERROR_APPLICATION_VERIFICATION_CALLBACK_CHECK = -2137657091; /* 0x8095F0FD */
|
||||
constexpr int SSL_ERROR_OUT_OF_MEMORY = -2137712683; /* 0x809517D5 */
|
||||
constexpr int SSL_ERROR_READ_TIMEOUT = -2137712880; /* 0x80951710 */
|
||||
constexpr int SSL_ERROR_SOCKET_CLOSED = -2137712883; /* 0x8095170D */
|
||||
constexpr int SSL_ERROR_BAD_LENGTH = -2137712781; /* 0x80951773 */
|
||||
constexpr int SSL_ERROR_INDEX_OOB = -2137712776; /* 0x80951778 */
|
||||
constexpr int SSL_ERROR_INVALID_ARG = -2137712774; /* 0x8095177A */
|
||||
constexpr int SSL_ERROR_EOF = -2137712772; /* 0x8095177C */
|
||||
constexpr int SSL_ERROR_BAD_EXPONENT = -2137712771; /* 0x8095177D */
|
||||
constexpr int SSL_ERROR_INCOMPLETE_SEARCH = -2137712770; /* 0x8095177E */
|
||||
constexpr int SSL_ERROR_INTERNAL_ERROR = -2137712769; /* 0x8095177F */
|
||||
constexpr int SSL_ERROR_BAD_CERT_LENGTH = -2137710382; /* 0x809520D2 */
|
||||
constexpr int SSL_ERROR_BAD_SIGN_ALGO = -2137710383; /* 0x809520D1 */
|
||||
constexpr int SSL_ERROR_MISMATCH_PUBLIC_KEYS = -2137710381; /* 0x809520D3 */
|
||||
constexpr int SSL_ERROR_KEY_BLOB_CORRUPT = -2137710380; /* 0x809520D4 */
|
||||
|
||||
constexpr int HTTP_ERROR_BEFORE_INIT = -2143088639; /*(0x80431001) */
|
||||
constexpr int HTTP_ERROR_ALREADY_INITED = -2143088608; /*(0x80431020) */
|
||||
constexpr int HTTP_ERROR_BUSY = -2143088607; /*(0x80431021) */
|
||||
constexpr int HTTP_ERROR_OUT_OF_MEMORY = -2143088606; /*(0x80431022) */
|
||||
constexpr int HTTP_ERROR_NOT_FOUND = -2143088603; /*(0x80431025) */
|
||||
constexpr int HTTP_ERROR_INVALID_VERSION = -2143088534; /*(0x8043106a) */
|
||||
constexpr int HTTP_ERROR_INVALID_ID = -2143088384; /*(0x80431100) */
|
||||
constexpr int HTTP_ERROR_OUT_OF_SIZE = -2143088380; /*(0x80431104) */
|
||||
constexpr int HTTP_ERROR_INVALID_VALUE = -2143088130; /*(0x804311fe) */
|
||||
constexpr int HTTP_ERROR_INVALID_URL = -2143080352; /*(0x80433060) */
|
||||
constexpr int HTTP_ERROR_UNKNOWN_SCHEME = -2143088543; /*(0x80431061) */
|
||||
constexpr int HTTP_ERROR_NETWORK = -2143088541; /*(0x80431063) */
|
||||
constexpr int HTTP_ERROR_BAD_RESPONSE = -2143088540; /*(0x80431064) */
|
||||
constexpr int HTTP_ERROR_BEFORE_SEND = -2143088539; /*(0x80431065) */
|
||||
constexpr int HTTP_ERROR_AFTER_SEND = -2143088538; /*(0x80431066) */
|
||||
constexpr int HTTP_ERROR_TIMEOUT = -2143088536; /*(0x80431068) */
|
||||
constexpr int HTTP_ERROR_UNKNOWN_AUTH_TYPE = -2143088535; /*(0x80431069) */
|
||||
constexpr int HTTP_ERROR_UNKNOWN_METHOD = -2143088533; /*(0x8043106b) */
|
||||
constexpr int HTTP_ERROR_READ_BY_HEAD_METHOD = -2143088529; /*(0x8043106f) */
|
||||
constexpr int HTTP_ERROR_NOT_IN_COM = -2143088528; /*(0x80431070) */
|
||||
constexpr int HTTP_ERROR_NO_CONTENT_LENGTH = -2143088527; /*(0x80431071) */
|
||||
constexpr int HTTP_ERROR_CHUNK_ENC = -2143088526; /*(0x80431072) */
|
||||
constexpr int HTTP_ERROR_TOO_LARGE_RESPONSE_HEADER = -2143088525; /*(0x80431073) */
|
||||
constexpr int HTTP_ERROR_SSL = -2143088523; /*(0x80431075) */
|
||||
constexpr int HTTP_ERROR_INSUFFICIENT_STACKSIZE = -2143088522; /*(0x80431076) */
|
||||
constexpr int HTTP_ERROR_ABORTED = -2143088512; /*(0x80431080) */
|
||||
constexpr int HTTP_ERROR_UNKNOWN = -2143088511; /*(0x80431081) */
|
||||
constexpr int HTTP_ERROR_EAGAIN = -2143088510; /*(0x80431082) */
|
||||
constexpr int HTTP_ERROR_PROXY = -2143088508; /*(0x80431084) */
|
||||
constexpr int HTTP_ERROR_BROKEN = -2143088507; /*(0x80431085) */
|
||||
constexpr int HTTP_ERROR_PARSE_HTTP_NOT_FOUND = -2143084507; /*(0x80432025) */
|
||||
constexpr int HTTP_ERROR_PARSE_HTTP_INVALID_RESPONSE = -2143084448; /*(0x80432060) */
|
||||
constexpr int HTTP_ERROR_PARSE_HTTP_INVALID_VALUE = -2143084034; /*(0x804321fe) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_EPACKET = -2143068159; /*(0x80436001) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_ENODNS = -2143068158; /*(0x80436002) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_ETIMEDOUT = -2143068157; /*(0x80436003) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_ENOSUPPORT = -2143068156; /*(0x80436004) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_EFORMAT = -2143068155; /*(0x80436005) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_ESERVERFAILURE = -2143068154; /*(0x80436006) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_ENOHOST = -2143068153; /*(0x80436007) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_ENOTIMPLEMENTED = -2143068152; /*(0x80436008) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_ESERVERREFUSED = -2143068151; /*(0x80436009) */
|
||||
constexpr int HTTP_ERROR_RESOLVER_ENORECORD = -2143068150; /*(0x8043600a) */
|
||||
constexpr int HTTPS_ERROR_CERT = -2143072160; /*(0x80435060) */
|
||||
constexpr int HTTPS_ERROR_HANDSHAKE = -2143072159; /*(0x80435061) */
|
||||
constexpr int HTTPS_ERROR_IO = -2143072158; /*(0x80435062) */
|
||||
constexpr int HTTPS_ERROR_INTERNAL = -2143072157; /*(0x80435063) */
|
||||
constexpr int HTTPS_ERROR_PROXY = -2143072156; /*(0x80435064) */
|
||||
|
||||
} // namespace Network
|
||||
|
||||
namespace PlayGo {
|
||||
|
||||
constexpr int PLAYGO_ERROR_UNKNOWN = -2135818239; /* 0x80B20001 */
|
||||
constexpr int PLAYGO_ERROR_FATAL = -2135818238; /* 0x80B20002 */
|
||||
constexpr int PLAYGO_ERROR_NO_MEMORY = -2135818237; /* 0x80B20003 */
|
||||
constexpr int PLAYGO_ERROR_INVALID_ARGUMENT = -2135818236; /* 0x80B20004 */
|
||||
constexpr int PLAYGO_ERROR_NOT_INITIALIZED = -2135818235; /* 0x80B20005 */
|
||||
constexpr int PLAYGO_ERROR_ALREADY_INITIALIZED = -2135818234; /* 0x80B20006 */
|
||||
constexpr int PLAYGO_ERROR_ALREADY_STARTED = -2135818233; /* 0x80B20007 */
|
||||
constexpr int PLAYGO_ERROR_NOT_STARTED = -2135818232; /* 0x80B20008 */
|
||||
constexpr int PLAYGO_ERROR_BAD_HANDLE = -2135818231; /* 0x80B20009 */
|
||||
constexpr int PLAYGO_ERROR_BAD_POINTER = -2135818230; /* 0x80B2000A */
|
||||
constexpr int PLAYGO_ERROR_BAD_SIZE = -2135818229; /* 0x80B2000B */
|
||||
constexpr int PLAYGO_ERROR_BAD_CHUNK_ID = -2135818228; /* 0x80B2000C */
|
||||
constexpr int PLAYGO_ERROR_BAD_SPEED = -2135818227; /* 0x80B2000D */
|
||||
constexpr int PLAYGO_ERROR_NOT_SUPPORT_PLAYGO = -2135818226; /* 0x80B2000E */
|
||||
constexpr int PLAYGO_ERROR_EPERM = -2135818225; /* 0x80B2000F */
|
||||
constexpr int PLAYGO_ERROR_BAD_LOCUS = -2135818224; /* 0x80B20010 */
|
||||
constexpr int PLAYGO_ERROR_NEED_DATA_DISC = -2135818223; /* 0x80B20011 */
|
||||
constexpr int PLAYGO_ERROR_BAD_OPTIONAL_TYPE = -2135818204; /* 0x80B20024 */
|
||||
|
||||
} // namespace PlayGo
|
||||
|
||||
namespace UserService {
|
||||
|
||||
constexpr int USER_SERVICE_ERROR_INTERNAL = -2137653247; /* 0x80960001 */
|
||||
constexpr int USER_SERVICE_ERROR_NOT_INITIALIZED = -2137653246; /* 0x80960002 */
|
||||
constexpr int USER_SERVICE_ERROR_ALREADY_INITIALIZED = -2137653245; /* 0x80960003 */
|
||||
constexpr int USER_SERVICE_ERROR_NO_MEMORY = -2137653244; /* 0x80960004 */
|
||||
constexpr int USER_SERVICE_ERROR_INVALID_ARGUMENT = -2137653243; /* 0x80960005 */
|
||||
constexpr int USER_SERVICE_ERROR_OPERATION_NOT_SUPPORTED = -2137653242; /* 0x80960006 */
|
||||
constexpr int USER_SERVICE_ERROR_NO_EVENT = -2137653241; /* 0x80960007 */
|
||||
constexpr int USER_SERVICE_ERROR_NOT_LOGGED_IN = -2137653239; /* 0x80960009 */
|
||||
constexpr int USER_SERVICE_ERROR_BUFFER_TOO_SHORT = -2137653238; /* 0x8096000A */
|
||||
|
||||
} // namespace UserService
|
||||
|
||||
namespace SaveData {
|
||||
|
||||
constexpr int SAVE_DATA_ERROR_PARAMETER = -2137063424; /* 0x809F0000 */
|
||||
constexpr int SAVE_DATA_ERROR_NOT_INITIALIZED = -2137063423; /* 0x809F0001 */
|
||||
constexpr int SAVE_DATA_ERROR_OUT_OF_MEMORY = -2137063422; /* 0x809F0002 */
|
||||
constexpr int SAVE_DATA_ERROR_BUSY = -2137063421; /* 0x809F0003 */
|
||||
constexpr int SAVE_DATA_ERROR_NOT_MOUNTED = -2137063420; /* 0x809F0004 */
|
||||
constexpr int SAVE_DATA_ERROR_NO_PERMISSION = -2137063419; /* 0x809F0005 */
|
||||
constexpr int SAVE_DATA_ERROR_FINGERPRINT_MISMATCH = -2137063418; /* 0x809F0006 */
|
||||
constexpr int SAVE_DATA_ERROR_EXISTS = -2137063417; /* 0x809F0007 */
|
||||
constexpr int SAVE_DATA_ERROR_NOT_FOUND = -2137063416; /* 0x809F0008 */
|
||||
constexpr int SAVE_DATA_ERROR_NO_SPACE_FS = -2137063414; /* 0x809F000A */
|
||||
constexpr int SAVE_DATA_ERROR_INTERNAL = -2137063413; /* 0x809F000B */
|
||||
constexpr int SAVE_DATA_ERROR_MOUNT_FULL = -2137063412; /* 0x809F000C */
|
||||
constexpr int SAVE_DATA_ERROR_BAD_MOUNTED = -2137063411; /* 0x809F000D */
|
||||
constexpr int SAVE_DATA_ERROR_FILE_NOT_FOUND = -2137063410; /* 0x809F000E */
|
||||
constexpr int SAVE_DATA_ERROR_BROKEN = -2137063409; /* 0x809F000F */
|
||||
constexpr int SAVE_DATA_ERROR_INVALID_LOGIN_USER = -2137063407; /* 0x809F0011 */
|
||||
constexpr int SAVE_DATA_ERROR_MEMORY_NOT_READY = -2137063406; /* 0x809F0012 */
|
||||
constexpr int SAVE_DATA_ERROR_BACKUP_BUSY = -2137063405; /* 0x809F0013 */
|
||||
constexpr int SAVE_DATA_ERROR_NOT_REGIST_CALLBACK = -2137063403; /* 0x809F0015 */
|
||||
constexpr int SAVE_DATA_ERROR_BUSY_FOR_SAVING = -2137063402; /* 0x809F0016 */
|
||||
constexpr int SAVE_DATA_ERROR_LIMITATION_OVER = -2137063401; /* 0x809F0017 */
|
||||
constexpr int SAVE_DATA_ERROR_EVENT_BUSY = -2137063400; /* 0x809F0018 */
|
||||
constexpr int SAVE_DATA_ERROR_PARAMSFO_TRANSFER_TITLE_ID_NOT_FOUND = -2137063399; /* 0x809F0019 */
|
||||
|
||||
} // namespace SaveData
|
||||
|
||||
} // namespace Libs
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_ERRNO_H_ */
|
||||
@@ -0,0 +1,808 @@
|
||||
//
|
||||
// Original algorithm is from:
|
||||
// https://github.com/mpaland/printf
|
||||
// Marco Paland (info@paland.com)
|
||||
// 2014-2019, PALANDesign Hannover, Germany
|
||||
// licensed under The MIT License (MIT)
|
||||
|
||||
#include "libs/guestPrintf.h"
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/vaContext.h"
|
||||
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
constexpr uint32_t FLAGS_ZEROPAD = (1U << 0U);
|
||||
constexpr uint32_t FLAGS_LEFT = (1U << 1U);
|
||||
constexpr uint32_t FLAGS_PLUS = (1U << 2U);
|
||||
constexpr uint32_t FLAGS_SPACE = (1U << 3U);
|
||||
constexpr uint32_t FLAGS_HASH = (1U << 4U);
|
||||
constexpr uint32_t FLAGS_UPPERCASE = (1U << 5U);
|
||||
constexpr uint32_t FLAGS_CHAR = (1U << 6U);
|
||||
constexpr uint32_t FLAGS_SHORT = (1U << 7U);
|
||||
constexpr uint32_t FLAGS_LONG = (1U << 8U);
|
||||
constexpr uint32_t FLAGS_LONG_LONG = (1U << 9U);
|
||||
constexpr uint32_t FLAGS_PRECISION = (1U << 10U);
|
||||
constexpr uint32_t FLAGS_ADAPT_EXP = (1U << 11U);
|
||||
|
||||
constexpr size_t PRINTF_NTOA_BUFFER_SIZE = 32U;
|
||||
constexpr size_t PRINTF_FTOA_BUFFER_SIZE = 32U;
|
||||
constexpr double PRINTF_MAX_FLOAT = 1e9;
|
||||
constexpr uint32_t PRINTF_DEFAULT_FLOAT_PRECISION = 6U;
|
||||
|
||||
using out_fct_type = void (*)(char character, std::vector<char>* buffer, size_t idx,
|
||||
size_t /*maxlen*/);
|
||||
|
||||
// internal null output
|
||||
static inline void _out_null(char character, std::vector<char>* buffer, size_t /*idx*/,
|
||||
size_t /*maxlen*/) {
|
||||
buffer->push_back(character);
|
||||
}
|
||||
|
||||
static inline bool _is_digit(char ch) {
|
||||
return (ch >= '0') && (ch <= '9');
|
||||
}
|
||||
|
||||
static unsigned int _atoi(const char** str) {
|
||||
unsigned int i = 0U;
|
||||
while (_is_digit(**str)) {
|
||||
i = i * 10U + static_cast<unsigned int>(*((*str)++) - '0');
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t _out_rev(out_fct_type out, std::vector<char>* buffer, size_t idx, size_t maxlen,
|
||||
const char* buf, size_t len, unsigned int width, unsigned int flags) {
|
||||
const size_t start_idx = idx;
|
||||
|
||||
// pad spaces up to given width
|
||||
if ((flags & FLAGS_LEFT) == 0 && (flags & FLAGS_ZEROPAD) == 0) {
|
||||
for (size_t i = len; i < width; i++) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
|
||||
// reverse string
|
||||
while (len != 0u) {
|
||||
out(buf[--len], buffer, idx++, maxlen);
|
||||
}
|
||||
|
||||
// append pad spaces up to given width
|
||||
if ((flags & FLAGS_LEFT) != 0u) {
|
||||
while (idx - start_idx < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
// internal itoa format
|
||||
static size_t _ntoa_format(out_fct_type out, std::vector<char>* buffer, size_t idx, size_t maxlen,
|
||||
char* buf, size_t len, bool negative, unsigned int base,
|
||||
unsigned int prec, unsigned int width, unsigned int flags) {
|
||||
// pad leading zeros
|
||||
if ((flags & FLAGS_LEFT) == 0u) {
|
||||
if ((width != 0u) && ((flags & FLAGS_ZEROPAD) != 0u) &&
|
||||
(negative || ((flags & (FLAGS_PLUS | FLAGS_SPACE)) != 0u))) {
|
||||
width--;
|
||||
}
|
||||
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
while (((flags & FLAGS_ZEROPAD) != 0u) && (len < width) &&
|
||||
(len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
// handle hash
|
||||
if ((flags & FLAGS_HASH) != 0u) {
|
||||
if (((flags & FLAGS_PRECISION) == 0u) && (len != 0u) && ((len == prec) || (len == width))) {
|
||||
len--;
|
||||
if ((len != 0u) && (base == 16U)) {
|
||||
len--;
|
||||
}
|
||||
}
|
||||
if ((base == 16U) && ((flags & FLAGS_UPPERCASE) == 0u) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'x';
|
||||
} else if ((base == 16U) && ((flags & FLAGS_UPPERCASE) != 0u) &&
|
||||
(len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'X';
|
||||
} else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'b';
|
||||
}
|
||||
if (len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if (len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
if (negative) {
|
||||
buf[len++] = '-';
|
||||
} else if ((flags & FLAGS_PLUS) != 0u) {
|
||||
buf[len++] = '+'; // ignore the space if the '+' exists
|
||||
} else if ((flags & FLAGS_SPACE) != 0u) {
|
||||
buf[len++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
|
||||
}
|
||||
|
||||
static size_t _ntoa_long_long(out_fct_type out, std::vector<char>* buffer, size_t idx,
|
||||
size_t maxlen, uint64_t value, bool negative, uint64_t base,
|
||||
unsigned int prec, unsigned int width, unsigned int flags) {
|
||||
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
|
||||
// no hash for 0 values
|
||||
if (value == 0u) {
|
||||
flags &= ~FLAGS_HASH;
|
||||
}
|
||||
|
||||
// write if precision != 0 and value is != 0
|
||||
if (((flags & FLAGS_PRECISION) == 0u) || (value != 0u)) {
|
||||
do {
|
||||
const char digit = static_cast<char>(value % base);
|
||||
// NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
|
||||
buf[len++] = digit < 10 ? '0' + digit
|
||||
: ((flags & FLAGS_UPPERCASE) != 0u ? 'A' : 'a') + digit - 10;
|
||||
value /= base;
|
||||
} while ((value != 0u) && (len < PRINTF_NTOA_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative,
|
||||
static_cast<unsigned int>(base), prec, width, flags);
|
||||
}
|
||||
|
||||
// internal itoa for 'long' type
|
||||
static size_t _ntoa_long(out_fct_type out, std::vector<char>* buffer, size_t idx, size_t maxlen,
|
||||
uint32_t value, bool negative, uint32_t base, unsigned int prec,
|
||||
unsigned int width, unsigned int flags) {
|
||||
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
|
||||
// no hash for 0 values
|
||||
if (value == 0u) {
|
||||
flags &= ~FLAGS_HASH;
|
||||
}
|
||||
|
||||
// write if precision != 0 and value is != 0
|
||||
if (((flags & FLAGS_PRECISION) == 0u) || (value != 0u)) {
|
||||
do {
|
||||
char digit = static_cast<char>(value % base);
|
||||
// NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
|
||||
buf[len++] = digit < 10 ? '0' + digit
|
||||
: ((flags & FLAGS_UPPERCASE) != 0u ? 'A' : 'a') + digit - 10;
|
||||
value /= base;
|
||||
} while ((value != 0u) && (len < PRINTF_NTOA_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative,
|
||||
static_cast<unsigned int>(base), prec, width, flags);
|
||||
}
|
||||
|
||||
static size_t _etoa(out_fct_type out, std::vector<char>* buffer, size_t idx, size_t maxlen,
|
||||
double value, unsigned int prec, unsigned int width, unsigned int flags);
|
||||
|
||||
// internal ftoa for fixed decimal floating point
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
static size_t _ftoa(out_fct_type out, std::vector<char>* buffer, size_t idx, size_t maxlen,
|
||||
double value, unsigned int prec, unsigned int width, unsigned int flags) {
|
||||
char buf[PRINTF_FTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
double diff = 0.0;
|
||||
|
||||
// powers of 10
|
||||
static const double pow10[] = {1, 10, 100, 1000, 10000,
|
||||
100000, 1000000, 10000000, 100000000, 1000000000};
|
||||
|
||||
// test for special values
|
||||
if (value != value) {
|
||||
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
|
||||
}
|
||||
if (value < -DBL_MAX) {
|
||||
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
|
||||
}
|
||||
if (value > DBL_MAX) {
|
||||
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) != 0u ? "fni+" : "fni",
|
||||
(flags & FLAGS_PLUS) != 0u ? 4U : 3U, width, flags);
|
||||
}
|
||||
|
||||
// test for very large values
|
||||
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of
|
||||
// characters overflowing your buffers == bad
|
||||
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
|
||||
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
|
||||
}
|
||||
|
||||
// test for negative
|
||||
bool negative = false;
|
||||
if (value < 0) {
|
||||
negative = true;
|
||||
value = 0 - value;
|
||||
}
|
||||
|
||||
// set default precision, if not set explicitly
|
||||
if ((flags & FLAGS_PRECISION) == 0u) {
|
||||
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
|
||||
}
|
||||
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
|
||||
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
|
||||
buf[len++] = '0';
|
||||
prec--;
|
||||
}
|
||||
|
||||
int whole = static_cast<int>(value);
|
||||
double tmp = (value - whole) * pow10[prec];
|
||||
auto frac = static_cast<uint32_t>(tmp);
|
||||
diff = tmp - frac;
|
||||
|
||||
if (diff > 0.5) {
|
||||
++frac;
|
||||
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
|
||||
if (frac >= pow10[prec]) {
|
||||
frac = 0;
|
||||
++whole;
|
||||
}
|
||||
} else if (diff < 0.5) {
|
||||
} else if ((frac == 0U) || ((frac & 1U) != 0u)) {
|
||||
// if halfway, round up if odd OR if last digit is 0
|
||||
++frac;
|
||||
}
|
||||
|
||||
if (prec == 0U) {
|
||||
diff = value - static_cast<double>(whole);
|
||||
if ((!(diff < 0.5) || (diff > 0.5)) && ((static_cast<uint32_t>(whole) & 1u) != 0)) {
|
||||
// exactly 0.5 and ODD, then round up
|
||||
// 1.5 -> 2, but 2.5 -> 2
|
||||
++whole;
|
||||
}
|
||||
} else {
|
||||
unsigned int count = prec;
|
||||
// now do fractional part, as an unsigned number
|
||||
while (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
--count;
|
||||
buf[len++] = static_cast<char>(48U + (frac % 10U));
|
||||
if ((frac /= 10U) == 0u) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// add extra 0s
|
||||
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
if (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
// add decimal
|
||||
buf[len++] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
// do whole part, number is reversed
|
||||
while (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
buf[len++] = static_cast<char>(48 + (whole % 10));
|
||||
if ((whole /= 10) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// pad leading zeros
|
||||
if (((flags & FLAGS_LEFT) == 0u) && ((flags & FLAGS_ZEROPAD) != 0u)) {
|
||||
if ((width != 0u) && (negative || ((flags & (FLAGS_PLUS | FLAGS_SPACE)) != 0u))) {
|
||||
width--;
|
||||
}
|
||||
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
if (negative) {
|
||||
buf[len++] = '-';
|
||||
} else if ((flags & FLAGS_PLUS) != 0u) {
|
||||
buf[len++] = '+'; // ignore the space if the '+' exists
|
||||
} else if ((flags & FLAGS_SPACE) != 0u) {
|
||||
buf[len++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
|
||||
}
|
||||
|
||||
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse
|
||||
// <m.jasperse@gmail.com>
|
||||
static size_t _etoa(out_fct_type out, std::vector<char>* buffer, size_t idx, size_t maxlen,
|
||||
double value, unsigned int prec, unsigned int width, unsigned int flags) {
|
||||
// check for NaN and special values
|
||||
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
|
||||
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
|
||||
}
|
||||
|
||||
// determine the sign
|
||||
const bool negative = value < 0;
|
||||
if (negative) {
|
||||
value = -value;
|
||||
}
|
||||
|
||||
// default precision
|
||||
if ((flags & FLAGS_PRECISION) == 0u) {
|
||||
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
|
||||
}
|
||||
|
||||
// determine the decimal exponent
|
||||
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
|
||||
union {
|
||||
uint64_t U;
|
||||
double F;
|
||||
} conv {};
|
||||
|
||||
conv.F = value;
|
||||
int exp2 = static_cast<int>((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
|
||||
conv.U = (conv.U & ((1ULL << 52U) - 1U)) |
|
||||
(1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
|
||||
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
|
||||
int expval = static_cast<int>(0.1760912590558 + exp2 * 0.301029995663981 +
|
||||
(conv.F - 1.5) * 0.289529654602168);
|
||||
// now we want to compute 10^expval but we want to be sure it won't overflow
|
||||
// exp2 = static_cast<int>(expval * 3.321928094887362 + 0.5);
|
||||
exp2 = static_cast<int>(lround(expval * 3.321928094887362));
|
||||
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
|
||||
const double z2 = z * z;
|
||||
conv.U = static_cast<uint64_t>(exp2 + 1023) << 52U;
|
||||
// compute exp(z) using continued fractions, see
|
||||
// https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
|
||||
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
|
||||
// correct for rounding errors
|
||||
if (value < conv.F) {
|
||||
expval--;
|
||||
conv.F /= 10;
|
||||
}
|
||||
|
||||
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
|
||||
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
|
||||
|
||||
// in "%g" mode, "prec" is the number of *significant figures* not decimals
|
||||
if ((flags & FLAGS_ADAPT_EXP) != 0u) {
|
||||
// do we want to fall-back to "%f" mode?
|
||||
if ((value >= 1e-4) && (value < 1e6)) {
|
||||
if (static_cast<int>(prec) > expval) {
|
||||
prec = static_cast<unsigned>(static_cast<int>(prec) - expval - 1);
|
||||
} else {
|
||||
prec = 0;
|
||||
}
|
||||
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
|
||||
// no characters in exponent
|
||||
minwidth = 0U;
|
||||
expval = 0;
|
||||
} else {
|
||||
// we use one sigfig for the whole part
|
||||
if ((prec > 0) && ((flags & FLAGS_PRECISION) != 0u)) {
|
||||
--prec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// will everything fit?
|
||||
unsigned int fwidth = width;
|
||||
if (width > minwidth) {
|
||||
// we didn't fall-back so subtract the characters required for the exponent
|
||||
fwidth -= minwidth;
|
||||
} else {
|
||||
// not enough characters, so go back to default sizing
|
||||
fwidth = 0U;
|
||||
}
|
||||
if (((flags & FLAGS_LEFT) != 0u) && (minwidth != 0u)) {
|
||||
// if we're padding on the right, DON'T pad the floating part
|
||||
fwidth = 0U;
|
||||
}
|
||||
|
||||
// rescale the float value
|
||||
if (expval != 0) {
|
||||
value /= conv.F;
|
||||
}
|
||||
|
||||
// output the floating part
|
||||
const size_t start_idx = idx;
|
||||
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth,
|
||||
flags & ~FLAGS_ADAPT_EXP);
|
||||
|
||||
// output the exponent part
|
||||
if (minwidth != 0u) {
|
||||
// output the exponential symbol
|
||||
out((flags & FLAGS_UPPERCASE) != 0u ? 'E' : 'e', buffer, idx++, maxlen);
|
||||
// output the exponent value
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10,
|
||||
0, minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS);
|
||||
// might need to right-pad spaces
|
||||
if ((flags & FLAGS_LEFT) != 0u) {
|
||||
while (idx - start_idx < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
static inline unsigned int _strnlen_s(const char* str, size_t maxsize) {
|
||||
const char* s = nullptr;
|
||||
for (s = str; (*s != 0) && ((maxsize--) != 0u); ++s) {
|
||||
;
|
||||
}
|
||||
return static_cast<unsigned int>(s - str);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
static int kyty_printf_internal(bool sn, char* sn_s, size_t sn_n, const char* format,
|
||||
VaList* va_list) {
|
||||
std::vector<char> buffer;
|
||||
|
||||
uint32_t flags = 0;
|
||||
uint32_t width = 0;
|
||||
uint32_t precision = 0;
|
||||
uint32_t n = 0;
|
||||
size_t idx = 0U;
|
||||
auto maxlen = static_cast<size_t>(-1);
|
||||
|
||||
// use null output function
|
||||
auto out = _out_null;
|
||||
|
||||
while (*format != 0) {
|
||||
// format specifier? %[flags][width][.precision][length]
|
||||
if (*format != '%') {
|
||||
// no
|
||||
out(*format, &buffer, idx++, maxlen);
|
||||
format++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// yes, evaluate it
|
||||
format++;
|
||||
|
||||
// evaluate flags
|
||||
flags = 0U;
|
||||
do {
|
||||
switch (*format) {
|
||||
case '0':
|
||||
flags |= FLAGS_ZEROPAD;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
case '-':
|
||||
flags |= FLAGS_LEFT;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
case '+':
|
||||
flags |= FLAGS_PLUS;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
case ' ':
|
||||
flags |= FLAGS_SPACE;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
case '#':
|
||||
flags |= FLAGS_HASH;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
default: n = 0U; break;
|
||||
}
|
||||
} while (n != 0u);
|
||||
|
||||
// evaluate width field
|
||||
width = 0U;
|
||||
if (_is_digit(*format)) {
|
||||
width = _atoi(&format);
|
||||
} else if (*format == '*') {
|
||||
// const int w = va_arg(va, int);
|
||||
const int w = VaArg_int(va_list);
|
||||
if (w < 0) {
|
||||
flags |= FLAGS_LEFT; // reverse padding
|
||||
width = static_cast<unsigned int>(-w);
|
||||
} else {
|
||||
width = static_cast<unsigned int>(w);
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
// evaluate precision field
|
||||
precision = 0U;
|
||||
if (*format == '.') {
|
||||
flags |= FLAGS_PRECISION;
|
||||
format++;
|
||||
if (_is_digit(*format)) {
|
||||
precision = _atoi(&format);
|
||||
} else if (*format == '*') {
|
||||
// const int prec = (int)va_arg(va, int);
|
||||
const int prec = VaArg_int(va_list);
|
||||
precision = prec > 0 ? static_cast<unsigned int>(prec) : 0U;
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate length field
|
||||
switch (*format) {
|
||||
case 'l':
|
||||
flags |= FLAGS_LONG;
|
||||
format++;
|
||||
if (*format == 'l') {
|
||||
flags |= FLAGS_LONG_LONG;
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
flags |= FLAGS_SHORT;
|
||||
format++;
|
||||
if (*format == 'h') {
|
||||
flags |= FLAGS_CHAR;
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
flags |= (sizeof(ptrdiff_t) == sizeof(int32_t) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
case 'j':
|
||||
flags |= (sizeof(intmax_t) == sizeof(int32_t) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
case 'z':
|
||||
flags |= (sizeof(size_t) == sizeof(int32_t) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// evaluate specifier
|
||||
switch (*format) {
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'o':
|
||||
case 'b': {
|
||||
// set the base
|
||||
unsigned int base = 0;
|
||||
if (*format == 'x' || *format == 'X') {
|
||||
base = 16U;
|
||||
} else if (*format == 'o') {
|
||||
base = 8U;
|
||||
} else if (*format == 'b') {
|
||||
base = 2U;
|
||||
} else {
|
||||
base = 10U;
|
||||
flags &= ~FLAGS_HASH; // no hash for dec format
|
||||
}
|
||||
// uppercase
|
||||
if (*format == 'X') {
|
||||
flags |= FLAGS_UPPERCASE;
|
||||
}
|
||||
|
||||
// no plus or space flag for u, x, X, o, b
|
||||
if ((*format != 'i') && (*format != 'd')) {
|
||||
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
|
||||
}
|
||||
|
||||
// ignore '0' flag when precision is given
|
||||
if ((flags & FLAGS_PRECISION) != 0u) {
|
||||
flags &= ~FLAGS_ZEROPAD;
|
||||
}
|
||||
|
||||
// convert the integer
|
||||
if ((*format == 'i') || (*format == 'd')) {
|
||||
// signed
|
||||
if ((flags & FLAGS_LONG_LONG) != 0u || (flags & FLAGS_LONG) != 0u) {
|
||||
// const long long value = va_arg(va, long long);
|
||||
auto value = VaArg_long_long(va_list);
|
||||
idx = _ntoa_long_long(out, &buffer, idx, maxlen,
|
||||
static_cast<uint64_t>(value > 0 ? value : 0 - value),
|
||||
value < 0, base, precision, width, flags);
|
||||
} else if ((flags & FLAGS_LONG) != 0u) {
|
||||
// const long value = va_arg(va, long);
|
||||
auto value = VaArg_long(va_list);
|
||||
idx = _ntoa_long(out, &buffer, idx, maxlen,
|
||||
static_cast<uint32_t>(value > 0 ? value : 0 - value),
|
||||
value < 0, base, precision, width, flags);
|
||||
} else {
|
||||
// const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int)
|
||||
// : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int)
|
||||
// : va_arg(va, int);
|
||||
int value =
|
||||
(flags & FLAGS_CHAR) != 0u ? static_cast<char>(VaArg_int(va_list))
|
||||
: (flags & FLAGS_SHORT) != 0u ? static_cast<int16_t>(VaArg_int(va_list))
|
||||
: VaArg_int(va_list);
|
||||
idx = _ntoa_long(out, &buffer, idx, maxlen,
|
||||
static_cast<unsigned int>(value > 0 ? value : 0 - value),
|
||||
value < 0, base, precision, width, flags);
|
||||
}
|
||||
} else {
|
||||
// unsigned
|
||||
if ((flags & FLAGS_LONG_LONG) != 0u || (flags & FLAGS_LONG) != 0u) {
|
||||
idx = _ntoa_long_long(out, &buffer, idx, maxlen,
|
||||
static_cast<uint64_t>(VaArg_long_long(va_list)),
|
||||
false, base, precision, width, flags);
|
||||
} else if ((flags & FLAGS_LONG) != 0u) {
|
||||
idx = _ntoa_long(out, &buffer, idx, maxlen,
|
||||
static_cast<uint32_t>(VaArg_long(va_list)), false, base,
|
||||
precision, width, flags);
|
||||
} else {
|
||||
const unsigned int value =
|
||||
(flags & FLAGS_CHAR) != 0u
|
||||
? static_cast<unsigned char>(VaArg_int(va_list))
|
||||
: (flags & FLAGS_SHORT) != 0u
|
||||
? static_cast<uint16_t>(VaArg_int(va_list))
|
||||
: static_cast<unsigned int>(VaArg_int(va_list));
|
||||
idx = _ntoa_long(out, &buffer, idx, maxlen, value, false, base, precision,
|
||||
width, flags);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
case 'F':
|
||||
if (*format == 'F') {
|
||||
flags |= FLAGS_UPPERCASE;
|
||||
}
|
||||
idx = _ftoa(out, &buffer, idx, maxlen, VaArg_double(va_list), precision, width,
|
||||
flags);
|
||||
format++;
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
if ((*format == 'g') || (*format == 'G')) {
|
||||
flags |= FLAGS_ADAPT_EXP;
|
||||
}
|
||||
if ((*format == 'E') || (*format == 'G')) {
|
||||
flags |= FLAGS_UPPERCASE;
|
||||
}
|
||||
idx = _etoa(out, &buffer, idx, maxlen, VaArg_double(va_list), precision, width,
|
||||
flags);
|
||||
format++;
|
||||
break;
|
||||
case 'c': {
|
||||
unsigned int l = 1U;
|
||||
// pre padding
|
||||
if ((flags & FLAGS_LEFT) == 0u) {
|
||||
while (l++ < width) {
|
||||
out(' ', &buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
// char output
|
||||
out(static_cast<char>(VaArg_int(va_list)), &buffer, idx++, maxlen);
|
||||
// post padding
|
||||
if ((flags & FLAGS_LEFT) != 0u) {
|
||||
while (l++ < width) {
|
||||
out(' ', &buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
// const char* p = va_arg(va, char*);
|
||||
const char* p = VaArg_ptr<const char>(va_list);
|
||||
unsigned int l =
|
||||
_strnlen_s(p, precision != 0u ? precision : static_cast<size_t>(-1));
|
||||
// pre padding
|
||||
if ((flags & FLAGS_PRECISION) != 0u) {
|
||||
l = (l < precision ? l : precision);
|
||||
}
|
||||
if ((flags & FLAGS_LEFT) == 0u) {
|
||||
while (l++ < width) {
|
||||
out(' ', &buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
// string output
|
||||
while ((*p != 0) && (((flags & FLAGS_PRECISION) == 0u) || ((precision--) != 0u))) {
|
||||
out(*(p++), &buffer, idx++, maxlen);
|
||||
}
|
||||
// post padding
|
||||
if ((flags & FLAGS_LEFT) != 0u) {
|
||||
while (l++ < width) {
|
||||
out(' ', &buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
width = sizeof(void*) * 2U;
|
||||
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
|
||||
const bool is_ll = sizeof(uintptr_t) == sizeof(int64_t);
|
||||
if (is_ll) {
|
||||
idx = _ntoa_long_long(out, &buffer, idx, maxlen,
|
||||
reinterpret_cast<uintptr_t>(VaArg_ptr<void>(va_list)),
|
||||
false, 16U, precision, width, flags);
|
||||
} else {
|
||||
idx = _ntoa_long(out, &buffer, idx, maxlen,
|
||||
static_cast<uint32_t>(
|
||||
reinterpret_cast<uintptr_t>(VaArg_ptr<void>(va_list))),
|
||||
false, 16U, precision, width, flags);
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
|
||||
case '%':
|
||||
out('%', &buffer, idx++, maxlen);
|
||||
format++;
|
||||
break;
|
||||
|
||||
default:
|
||||
out(*format, &buffer, idx++, maxlen);
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// termination
|
||||
out(static_cast<char>(0), &buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
|
||||
|
||||
if (sn) {
|
||||
int s = snprintf(sn_s, sn_n, "%s", buffer.data());
|
||||
EXIT_NOT_IMPLEMENTED(static_cast<size_t>(s) >= sn_n);
|
||||
} else {
|
||||
LOGF_COLOR(Log::Color::BrightMagenta, "%s", buffer.data());
|
||||
}
|
||||
|
||||
// return written chars without terminating \0
|
||||
return static_cast<int>(idx);
|
||||
}
|
||||
|
||||
static int kyty_vprintf(const char* format, VaList* va_list) {
|
||||
return kyty_printf_internal(false, nullptr, 0, format, va_list);
|
||||
}
|
||||
|
||||
static int kyty_printf_ctx(VaContext* ctx) {
|
||||
const char* format = VaArg_ptr<const char>(&ctx->va_list);
|
||||
|
||||
return kyty_printf_internal(false, nullptr, 0, format, &ctx->va_list);
|
||||
}
|
||||
|
||||
static int kyty_snprintf_ctx(VaContext* ctx) {
|
||||
char* s = VaArg_ptr<char>(&ctx->va_list);
|
||||
size_t n = VaArg_size_t(&ctx->va_list);
|
||||
const char* format = VaArg_ptr<const char>(&ctx->va_list);
|
||||
|
||||
return kyty_printf_internal(true, s, n, format, &ctx->va_list);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI kyty_printf_std(VA_ARGS) {
|
||||
VA_CONTEXT(ctx); // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
|
||||
return kyty_printf_ctx(&ctx);
|
||||
}
|
||||
|
||||
guest_printf_std_func_t GetGuestPrintfStdFunc() {
|
||||
return reinterpret_cast<guest_printf_std_func_t>(kyty_printf_std);
|
||||
}
|
||||
|
||||
guest_printf_ctx_func_t GetGuestPrintfCtxFunc() {
|
||||
return kyty_printf_ctx;
|
||||
}
|
||||
|
||||
guest_snprintf_ctx_func_t GetGuestSnprintfCtxFunc() {
|
||||
return kyty_snprintf_ctx;
|
||||
}
|
||||
|
||||
guest_vprintf_func_t GetGuestVprintfFunc() {
|
||||
return kyty_vprintf;
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_GUEST_PRINTF_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_GUEST_PRINTF_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
|
||||
namespace Libs {
|
||||
|
||||
struct VaContext;
|
||||
struct VaList;
|
||||
|
||||
using guest_printf_std_func_t = KYTY_FORMAT_PRINTF(1, 2) KYTY_SYSV_ABI
|
||||
int (*)(const char* str, ...);
|
||||
using guest_printf_ctx_func_t = int (*)(VaContext* c);
|
||||
using guest_snprintf_ctx_func_t = int (*)(VaContext* c);
|
||||
using guest_vprintf_func_t = int (*)(const char* str, VaList* c);
|
||||
|
||||
guest_printf_std_func_t GetGuestPrintfStdFunc();
|
||||
guest_printf_ctx_func_t GetGuestPrintfCtxFunc();
|
||||
guest_snprintf_ctx_func_t GetGuestSnprintfCtxFunc();
|
||||
guest_vprintf_func_t GetGuestVprintfFunc();
|
||||
|
||||
} // namespace Libs
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_GUEST_PRINTF_H_ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,254 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
#include "loader/systemContent.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <system_error>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("AppContent", 1, "AppContentUtil", 1, 1);
|
||||
|
||||
namespace AppContent {
|
||||
|
||||
constexpr uint32_t APP_CONTENT_APPPARAM_SKU_FLAG_FULL = 3;
|
||||
constexpr int APP_CONTENT_ERROR_PARAMETER = -2133262334; /* 0x80D90002 */
|
||||
constexpr int APP_CONTENT_ERROR_NOT_MOUNTED = -2133262332; /* 0x80D90004 */
|
||||
constexpr int APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT = -2133262329; /* 0x80D90007 */
|
||||
|
||||
static std::string g_title_id;
|
||||
|
||||
struct AppContentInitParam {
|
||||
char reserved[32];
|
||||
};
|
||||
|
||||
struct AppContentBootParam {
|
||||
char reserved1[4];
|
||||
uint32_t attr;
|
||||
char reserved2[32];
|
||||
};
|
||||
|
||||
struct AppContentMountPoint {
|
||||
char data[16];
|
||||
};
|
||||
|
||||
struct NpUnifiedEntitlementLabel {
|
||||
char data[17];
|
||||
char padding[3];
|
||||
};
|
||||
|
||||
static bool TryGetTitleIdFromContentId(std::string* title_id) {
|
||||
std::string content_id;
|
||||
if (!Loader::SystemContentParamSfoGetString("CONTENT_ID", &content_id) || content_id.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t dash = Common::FindIndex(content_id, '-');
|
||||
if (!Common::IndexValid(content_id, dash)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t underscore = Common::FindIndex(content_id, '_', dash + 1);
|
||||
if (!Common::IndexValid(content_id, underscore) || underscore <= dash + 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*title_id = Common::Mid(content_id, dash + 1, underscore - dash - 1);
|
||||
return !title_id->empty();
|
||||
}
|
||||
|
||||
static bool ResolveTitleId(std::string* title_id) {
|
||||
if (Loader::SystemContentParamSfoGetString("TITLE_ID", title_id) && !title_id->empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TryGetTitleIdFromContentId(title_id)) {
|
||||
LOGF("\t PS5 mode: TITLE_ID missing, using CONTENT_ID title segment\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AppContentInitialize(const AppContentInitParam* init_param,
|
||||
AppContentBootParam* boot_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t init_param = 0x%016" PRIx64 "\n"
|
||||
"\t boot_param = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(init_param), reinterpret_cast<uint64_t>(boot_param));
|
||||
|
||||
if (boot_param != nullptr) {
|
||||
std::memset(boot_param, 0, sizeof(*boot_param));
|
||||
}
|
||||
|
||||
if (ResolveTitleId(&g_title_id)) {
|
||||
LOGF("\t title_id = %s\n", g_title_id.c_str());
|
||||
} else {
|
||||
LOGF("\t TITLE_ID missing\n");
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AppContentAppParamGetInt(uint32_t param_id, int32_t* value) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(value == nullptr);
|
||||
|
||||
*value = 0;
|
||||
bool found = false;
|
||||
|
||||
LOGF("\t param_id = %u\n", param_id);
|
||||
|
||||
switch (param_id) {
|
||||
case 0:
|
||||
*value = APP_CONTENT_APPPARAM_SKU_FLAG_FULL;
|
||||
found = true;
|
||||
break;
|
||||
case 1: found = Loader::SystemContentParamSfoGetInt("USER_DEFINED_PARAM_1", value); break;
|
||||
case 2: found = Loader::SystemContentParamSfoGetInt("USER_DEFINED_PARAM_2", value); break;
|
||||
case 3: found = Loader::SystemContentParamSfoGetInt("USER_DEFINED_PARAM_3", value); break;
|
||||
case 4: found = Loader::SystemContentParamSfoGetInt("USER_DEFINED_PARAM_4", value); break;
|
||||
default: EXIT("unknown param_id: %u\n", param_id);
|
||||
}
|
||||
|
||||
LOGF("\t value = %d [%s]\n", *value, found ? "found" : "not found");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AppContentDownloadDataGetAvailableSpaceKb(const AppContentMountPoint* mount_point,
|
||||
size_t* available_space_kb) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t mount_point = 0x%016" PRIx64 "\n"
|
||||
"\t available_space_kb = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(mount_point), reinterpret_cast<uint64_t>(available_space_kb));
|
||||
|
||||
if (available_space_kb == nullptr) {
|
||||
return APP_CONTENT_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
const auto space = std::filesystem::space(std::filesystem::current_path(), ec);
|
||||
if (ec) {
|
||||
LOGF("\t filesystem::space failed: %s\n", ec.message().c_str());
|
||||
*available_space_kb = 1024u * 1024u;
|
||||
} else {
|
||||
*available_space_kb = static_cast<size_t>(space.available / 1024u);
|
||||
}
|
||||
|
||||
if (mount_point != nullptr) {
|
||||
char mount_name[sizeof(mount_point->data) + 1] {};
|
||||
std::memcpy(mount_name, mount_point->data, sizeof(mount_point->data));
|
||||
LOGF("\t mount = %s\n", mount_name);
|
||||
}
|
||||
LOGF("\t available_space_kb = %" PRIu64 "\n", static_cast<uint64_t>(*available_space_kb));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AppContentAddcontMount(uint32_t service_label,
|
||||
const NpUnifiedEntitlementLabel* entitlement_label,
|
||||
AppContentMountPoint* mount_point) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t service_label = %" PRIu32 "\n"
|
||||
"\t entitlement_label = 0x%016" PRIx64 "\n"
|
||||
"\t mount_point = 0x%016" PRIx64 "\n",
|
||||
service_label, reinterpret_cast<uint64_t>(entitlement_label),
|
||||
reinterpret_cast<uint64_t>(mount_point));
|
||||
|
||||
if (entitlement_label == nullptr || mount_point == nullptr) {
|
||||
return APP_CONTENT_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
std::memset(mount_point->data, 0, sizeof(mount_point->data));
|
||||
|
||||
return APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AppContentAddcontUnmount(const AppContentMountPoint* mount_point) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t mount_point = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(mount_point));
|
||||
|
||||
if (mount_point == nullptr) {
|
||||
return APP_CONTENT_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
if (mount_point->data[0] == '\0') {
|
||||
return APP_CONTENT_ERROR_NOT_MOUNTED;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace AppContent
|
||||
|
||||
namespace LibAppContentTemporary {
|
||||
|
||||
namespace AppContentTemporary {
|
||||
|
||||
using AppContentMountPoint = AppContent::AppContentMountPoint;
|
||||
|
||||
static int KYTY_SYSV_ABI AppContentTemporaryDataMount2(uint32_t option,
|
||||
AppContentMountPoint* mount_point) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t option = 0x%08" PRIx32 "\n"
|
||||
"\t mount_point = 0x%016" PRIx64 "\n",
|
||||
option, reinterpret_cast<uint64_t>(mount_point));
|
||||
|
||||
if (mount_point == nullptr) {
|
||||
return AppContent::APP_CONTENT_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
std::memset(mount_point->data, 0, sizeof(mount_point->data));
|
||||
std::memcpy(mount_point->data, "/temp0", sizeof("/temp0") - 1);
|
||||
|
||||
LOGF("\t mount = %s\n", mount_point->data);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI AppContentTemporaryDataFormat(const AppContentMountPoint* mount_point) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t mount_point = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(mount_point));
|
||||
|
||||
if (mount_point == nullptr) {
|
||||
return AppContent::APP_CONTENT_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace AppContentTemporary
|
||||
|
||||
LIB_DEFINE(InitAppContent_1_Temporary) {
|
||||
LIB_FUNC("buYbeLOGWmA", AppContentTemporary::AppContentTemporaryDataMount2);
|
||||
LIB_FUNC("a5N7lAG0y2Q", AppContentTemporary::AppContentTemporaryDataFormat);
|
||||
}
|
||||
|
||||
} // namespace LibAppContentTemporary
|
||||
|
||||
LIB_DEFINE(InitAppContent_1) {
|
||||
LIB_FUNC("R9lA82OraNs", AppContent::AppContentInitialize);
|
||||
LIB_FUNC("99b82IKXpH4", AppContent::AppContentAppParamGetInt);
|
||||
LIB_FUNC("VANhIWcqYak", AppContent::AppContentAddcontMount);
|
||||
LIB_FUNC("3rHWaV-1KC4", AppContent::AppContentAddcontUnmount);
|
||||
LIB_FUNC("Gl6w5i0JokY", AppContent::AppContentDownloadDataGetAvailableSpaceKb);
|
||||
LibAppContentTemporary::InitAppContent_1_Temporary(s);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,929 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/threads.h"
|
||||
#include "kernel/pthread.h"
|
||||
#include "libs/audio.h"
|
||||
#include "libs/audio_internal.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs::Audio {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int AUDIO_OUT_PORT_TYPE_MAIN = 0;
|
||||
constexpr int AUDIO_OUT_PORT_TYPE_BGM = 1;
|
||||
constexpr int AUDIO_OUT_PORT_TYPE_VOICE = 2;
|
||||
constexpr int AUDIO_OUT_PORT_TYPE_PERSONAL = 3;
|
||||
constexpr int AUDIO_OUT_PORT_TYPE_PADSPK = 4;
|
||||
constexpr int AUDIO_OUT_PORT_TYPE_VIBRATION = 10;
|
||||
constexpr int AUDIO_OUT_PORT_TYPE_AUX = 127;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace AudioOut2 {
|
||||
|
||||
LIB_NAME("AudioOut2", "AudioOut");
|
||||
|
||||
struct AudioOut2ContextParam {
|
||||
uint32_t max_ports;
|
||||
uint32_t max_object_ports;
|
||||
uint32_t guarantee_object_ports;
|
||||
uint32_t queue_depth;
|
||||
uint32_t num_grains;
|
||||
uint32_t flags;
|
||||
uint32_t reserved[10];
|
||||
};
|
||||
|
||||
struct AudioOut2PortParam {
|
||||
uint16_t port_type;
|
||||
uint16_t pad;
|
||||
uint32_t data_format;
|
||||
uint32_t sampling_freq;
|
||||
uint32_t flags;
|
||||
AudioOut2UserHandle user_handle;
|
||||
uint32_t reserved[10];
|
||||
};
|
||||
|
||||
struct AudioOut2Attribute {
|
||||
uint32_t attribute_id;
|
||||
int32_t reserved;
|
||||
const void* value;
|
||||
size_t value_size;
|
||||
};
|
||||
|
||||
struct AudioOut2Pcm {
|
||||
const void* data;
|
||||
};
|
||||
|
||||
struct AudioOut2Position {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
struct AudioOut2PortState {
|
||||
uint16_t output;
|
||||
uint8_t num_channels;
|
||||
uint8_t pad1;
|
||||
int16_t volume;
|
||||
uint16_t reroute_counter;
|
||||
uint32_t flags;
|
||||
uint32_t pad2;
|
||||
uint64_t reserved[6];
|
||||
};
|
||||
|
||||
struct AudioOut2SystemState {
|
||||
float loudness;
|
||||
uint32_t pad;
|
||||
uint64_t reserved[7];
|
||||
};
|
||||
|
||||
struct AudioOut2SpeakerAngle {
|
||||
int16_t azimuth;
|
||||
int16_t elevation;
|
||||
};
|
||||
|
||||
struct AudioOut2SpeakerInfo {
|
||||
uint8_t type;
|
||||
uint8_t pad1;
|
||||
int16_t pad2;
|
||||
uint32_t available_bits;
|
||||
uint32_t flags;
|
||||
uint32_t pad3;
|
||||
AudioOut2SpeakerAngle speaker_angle[16];
|
||||
};
|
||||
|
||||
struct AudioOut2SystemDebugStateParam {
|
||||
uint32_t debug_state_id;
|
||||
int32_t reserved;
|
||||
void* param;
|
||||
size_t param_size;
|
||||
};
|
||||
|
||||
struct AudioOut2MasteringParamsHeader {
|
||||
uint32_t params_id;
|
||||
};
|
||||
|
||||
struct AudioOut2MasteringStatesHeader {
|
||||
uint32_t states_id;
|
||||
};
|
||||
|
||||
struct AudioOut2MasteringStatesDescriptor {
|
||||
uint32_t id;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_MAX_SYSTEM_CHANNELS = 8;
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_COMPRESSOR_BANDS = 3;
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_COMPRESSOR_BANDS_V2 = 4;
|
||||
|
||||
struct AudioOut2MasteringCompressorStates {
|
||||
AudioOut2MasteringStatesDescriptor descriptor;
|
||||
uint32_t reserved[2];
|
||||
float input_rms[AUDIO_OUT2_MASTERING_COMPRESSOR_BANDS]
|
||||
[AUDIO_OUT2_MASTERING_MAX_SYSTEM_CHANNELS];
|
||||
float compression_coeff[AUDIO_OUT2_MASTERING_COMPRESSOR_BANDS]
|
||||
[AUDIO_OUT2_MASTERING_MAX_SYSTEM_CHANNELS];
|
||||
};
|
||||
|
||||
struct AudioOut2MasteringCompressorStatesV2 {
|
||||
AudioOut2MasteringStatesDescriptor descriptor;
|
||||
uint32_t reserved[2];
|
||||
float input_rms[AUDIO_OUT2_MASTERING_COMPRESSOR_BANDS_V2]
|
||||
[AUDIO_OUT2_MASTERING_MAX_SYSTEM_CHANNELS];
|
||||
float compression_coeff[AUDIO_OUT2_MASTERING_COMPRESSOR_BANDS_V2]
|
||||
[AUDIO_OUT2_MASTERING_MAX_SYSTEM_CHANNELS];
|
||||
};
|
||||
|
||||
struct AudioOut2MasteringLimiterStates {
|
||||
AudioOut2MasteringStatesDescriptor descriptor;
|
||||
uint32_t reserved[2];
|
||||
float input_peak[AUDIO_OUT2_MASTERING_MAX_SYSTEM_CHANNELS];
|
||||
float output_peak[AUDIO_OUT2_MASTERING_MAX_SYSTEM_CHANNELS];
|
||||
float gain_peak[AUDIO_OUT2_MASTERING_MAX_SYSTEM_CHANNELS];
|
||||
};
|
||||
|
||||
struct AudioOut2MasteringStates {
|
||||
AudioOut2MasteringStatesHeader states_header;
|
||||
uint32_t reserved[3];
|
||||
AudioOut2MasteringCompressorStates compressor_states;
|
||||
AudioOut2MasteringLimiterStates limiter_states;
|
||||
};
|
||||
|
||||
struct AudioOut2MasteringStatesV2 {
|
||||
AudioOut2MasteringStatesHeader states_header;
|
||||
uint32_t reserved[3];
|
||||
AudioOut2MasteringCompressorStatesV2 compressor_states;
|
||||
AudioOut2MasteringLimiterStates limiter_states;
|
||||
};
|
||||
|
||||
static std::atomic_uint64_t g_audioout2_next_context {1};
|
||||
static std::atomic_uint64_t g_audioout2_next_port {1};
|
||||
static std::atomic_uint64_t g_audioout2_next_user {1};
|
||||
|
||||
struct AudioOut2ContextState {
|
||||
bool used = false;
|
||||
AudioOut2ContextHandle handle = 0;
|
||||
uint32_t queue_depth = 4;
|
||||
uint32_t queued = 0;
|
||||
uint32_t num_grains = 512;
|
||||
uint64_t last_update = 0;
|
||||
};
|
||||
|
||||
struct AudioOut2PortStateEntry {
|
||||
bool used = false;
|
||||
AudioOut2PortHandle handle = 0;
|
||||
AudioOut2ContextHandle context = 0;
|
||||
uint16_t port_type = 0;
|
||||
uint32_t data_format = 0;
|
||||
uint32_t sampling_freq = 48000;
|
||||
uint32_t samples_num = 512;
|
||||
AudioInternal::Format audio_format = AudioInternal::Format::Unknown;
|
||||
int audio_handle = 0;
|
||||
const void* pcm_data = nullptr;
|
||||
};
|
||||
|
||||
struct AudioOut2SpeakerArrayState {
|
||||
bool used = false;
|
||||
uint32_t num_speakers = 0;
|
||||
uint8_t is_3d = 0;
|
||||
uint8_t is_ambisonics = 0;
|
||||
AudioOut2SpeakerArrayHandle handle = nullptr;
|
||||
};
|
||||
|
||||
struct AudioOut2LatencyState {
|
||||
bool used = false;
|
||||
uint32_t user_id = 0;
|
||||
uint32_t output = 0;
|
||||
uint32_t latency_us = 0;
|
||||
};
|
||||
|
||||
static Common::Mutex g_audioout2_context_mutex;
|
||||
static std::array<AudioOut2ContextState, 16> g_audioout2_contexts;
|
||||
static Common::Mutex g_audioout2_port_mutex;
|
||||
static std::array<AudioOut2PortStateEntry, 256> g_audioout2_ports;
|
||||
static Common::Mutex g_audioout2_speaker_array_mutex;
|
||||
static std::array<AudioOut2SpeakerArrayState, 32> g_audioout2_speaker_arrays;
|
||||
static Common::Mutex g_audioout2_latency_mutex;
|
||||
static std::array<AudioOut2LatencyState, 16> g_audioout2_latencies;
|
||||
|
||||
static constexpr int AUDIO_OUT2_ERROR_NOT_READY = -2144960504; /* 0x80268008 */
|
||||
static constexpr int AUDIO_OUT2_ERROR_PORT_FULL = -2144960494; /* 0x80268012 */
|
||||
static constexpr int AUDIO_OUT2_ERROR_INVALID_PARAM = -2144960511; /* 0x80268001 */
|
||||
static constexpr int AUDIO_OUT2_ERROR_MASTERING_INVALID_API_PARAM = -2144959999; /* 0x80268201 */
|
||||
static constexpr int AUDIO_OUT2_ERROR_MASTERING_INVALID_STATES_ID = -2144959996; /* 0x80268204 */
|
||||
static constexpr uint32_t AUDIO_OUT2_PORT_ATTRIBUTE_ID_PCM = 0;
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_OUTPUT_RECORDING = 2;
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_STATES_ID_DEFAULT = 1;
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_STATES_ID_V2 = 2;
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_STATES_STRUCT_ID_COMPRESSOR_DEFAULT = 0x01010001;
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_STATES_STRUCT_ID_COMPRESSOR_V2 = 0x01020001;
|
||||
static constexpr uint32_t AUDIO_OUT2_MASTERING_STATES_STRUCT_ID_LIMITER_DEFAULT = 0x01010003;
|
||||
|
||||
static AudioOut2ContextState* audioout2_find_context_locked(AudioOut2ContextHandle ctx) {
|
||||
for (auto& state: g_audioout2_contexts) {
|
||||
if (state.used && state.handle == ctx) {
|
||||
return &state;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static uint32_t audioout2_grain_micros(uint32_t grains) {
|
||||
const auto sample_count = (grains == 0 ? 512u : grains);
|
||||
return std::max<uint32_t>((sample_count * 1000000u) / 48000u, 1000u);
|
||||
}
|
||||
|
||||
static uint8_t audioout2_data_format_channels(uint32_t data_format) {
|
||||
const auto channels = (data_format >> 8u) & 0xffu;
|
||||
return static_cast<uint8_t>(channels == 0 ? 2u : std::min(channels, 16u));
|
||||
}
|
||||
|
||||
static AudioInternal::Format audioout2_data_format_to_audio_format(uint32_t data_format) {
|
||||
const auto channels = audioout2_data_format_channels(data_format);
|
||||
const auto data_type = data_format & 0x7fu;
|
||||
const auto is_std = (data_format & 0x80u) != 0;
|
||||
|
||||
switch (data_type) {
|
||||
case 0:
|
||||
switch (channels) {
|
||||
case 1: return AudioInternal::Format::FloatMono;
|
||||
case 2: return AudioInternal::Format::FloatStereo;
|
||||
case 8:
|
||||
return is_std ? AudioInternal::Format::Float8ChStd
|
||||
: AudioInternal::Format::Float8Ch;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
switch (channels) {
|
||||
case 1: return AudioInternal::Format::Signed16bitMono;
|
||||
case 2: return AudioInternal::Format::Signed16bitStereo;
|
||||
case 8:
|
||||
return is_std ? AudioInternal::Format::Signed16bit8ChStd
|
||||
: AudioInternal::Format::Signed16bit8Ch;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return AudioInternal::Format::Unknown;
|
||||
}
|
||||
|
||||
static int audioout2_port_type_to_audio_out_type(uint16_t port_type) {
|
||||
switch (port_type & 0xffu) {
|
||||
case 0: return AUDIO_OUT_PORT_TYPE_MAIN;
|
||||
case 1: return AUDIO_OUT_PORT_TYPE_BGM;
|
||||
case 2: return AUDIO_OUT_PORT_TYPE_VOICE;
|
||||
case 3: return AUDIO_OUT_PORT_TYPE_PADSPK;
|
||||
case 4: return AUDIO_OUT_PORT_TYPE_PERSONAL;
|
||||
case 5: return AUDIO_OUT_PORT_TYPE_AUX;
|
||||
case 6: return AUDIO_OUT_PORT_TYPE_VIBRATION;
|
||||
default: return AUDIO_OUT_PORT_TYPE_MAIN;
|
||||
}
|
||||
}
|
||||
|
||||
static bool audioout2_port_type_is_object(uint16_t port_type) {
|
||||
return (port_type & 0xff00u) == 0x0100u;
|
||||
}
|
||||
|
||||
static void audioout2_update_context_locked(AudioOut2ContextState* state) {
|
||||
if (state == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = LibKernel::KernelGetProcessTime();
|
||||
if (state->last_update == 0 || state->queued == 0) {
|
||||
state->last_update = now;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto grain_micros = static_cast<uint64_t>(audioout2_grain_micros(state->num_grains));
|
||||
if (now <= state->last_update || grain_micros == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto elapsed = now - state->last_update;
|
||||
const auto drained = std::min<uint64_t>(state->queued, elapsed / grain_micros);
|
||||
if (drained == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->queued -= static_cast<uint32_t>(drained);
|
||||
state->last_update += drained * grain_micros;
|
||||
if (state->queued == 0) {
|
||||
state->last_update = now;
|
||||
}
|
||||
}
|
||||
|
||||
static AudioOut2PortStateEntry* audioout2_find_port_locked(AudioOut2PortHandle port) {
|
||||
for (auto& state: g_audioout2_ports) {
|
||||
if (state.used && state.handle == port) {
|
||||
return &state;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static uint32_t audioout2_context_grains(AudioOut2ContextHandle ctx) {
|
||||
uint32_t samples_num = 512;
|
||||
|
||||
g_audioout2_context_mutex.Lock();
|
||||
if (auto* state = audioout2_find_context_locked(ctx); state != nullptr) {
|
||||
samples_num = (state->num_grains == 0 ? 512u : state->num_grains);
|
||||
}
|
||||
g_audioout2_context_mutex.Unlock();
|
||||
|
||||
return samples_num;
|
||||
}
|
||||
|
||||
static void audioout2_queue_context_audio(AudioOut2ContextHandle ctx) {
|
||||
std::vector<AudioInternal::OutputParam> params;
|
||||
params.reserve(AudioInternal::OUT_PORTS_MAX);
|
||||
|
||||
g_audioout2_port_mutex.Lock();
|
||||
for (const auto& state: g_audioout2_ports) {
|
||||
if (state.used && state.context == ctx && state.audio_handle > 0 &&
|
||||
state.pcm_data != nullptr && params.size() < AudioInternal::OUT_PORTS_MAX) {
|
||||
params.push_back(AudioInternal::OutputParam {state.audio_handle, state.pcm_data});
|
||||
}
|
||||
}
|
||||
g_audioout2_port_mutex.Unlock();
|
||||
|
||||
if (params.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)AudioInternal::AudioOutOutputs(params.data(), static_cast<uint32_t>(params.size()));
|
||||
}
|
||||
|
||||
static void audioout2_close_audio_handle(int audio_handle) {
|
||||
if (audio_handle > 0) {
|
||||
AudioInternal::AudioOutClose(audio_handle);
|
||||
}
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2Initialize() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2ContextResetParam(AudioOut2ContextParam* params) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(params == nullptr);
|
||||
|
||||
std::memset(params, 0, sizeof(AudioOut2ContextParam));
|
||||
params->max_ports = 256;
|
||||
params->max_object_ports = 256;
|
||||
params->guarantee_object_ports = 0;
|
||||
params->queue_depth = 4;
|
||||
params->num_grains = 512;
|
||||
params->flags = 1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2ContextQueryMemory(const AudioOut2ContextParam* params,
|
||||
size_t* memory_size) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(params == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(memory_size == nullptr);
|
||||
|
||||
const auto queue_depth = (params->queue_depth == 0 ? 4u : params->queue_depth);
|
||||
*memory_size = 0x10000u + static_cast<size_t>(queue_depth) * 0x590u;
|
||||
|
||||
LOGF("\t memory_size = 0x%016" PRIx64 "\n", static_cast<uint64_t>(*memory_size));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2ContextCreate(const AudioOut2ContextParam* params, void* buffer,
|
||||
size_t buffer_size, AudioOut2ContextHandle* ctx) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(params == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(ctx == nullptr);
|
||||
|
||||
*ctx = g_audioout2_next_context.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
g_audioout2_context_mutex.Lock();
|
||||
auto* state = audioout2_find_context_locked(0);
|
||||
if (state == nullptr) {
|
||||
for (auto& candidate: g_audioout2_contexts) {
|
||||
if (!candidate.used) {
|
||||
state = &candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXIT_NOT_IMPLEMENTED(state == nullptr);
|
||||
*state = AudioOut2ContextState {};
|
||||
state->used = true;
|
||||
state->handle = *ctx;
|
||||
state->queue_depth = (params->queue_depth == 0 ? 4u : params->queue_depth);
|
||||
state->queued = 0;
|
||||
state->num_grains = (params->num_grains == 0 ? 512u : params->num_grains);
|
||||
state->last_update = LibKernel::KernelGetProcessTime();
|
||||
g_audioout2_context_mutex.Unlock();
|
||||
|
||||
LOGF("\t buffer = 0x%016" PRIx64 "\n"
|
||||
"\t buffer_size = 0x%016" PRIx64 "\n"
|
||||
"\t ctx = 0x%016" PRIx64 "\n"
|
||||
"\t queue_depth = %" PRIu32 ", num_grains = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(buffer), static_cast<uint64_t>(buffer_size), *ctx,
|
||||
state->queue_depth, state->num_grains);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2ContextDestroy(AudioOut2ContextHandle ctx) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t ctx = 0x%016" PRIx64 "\n", ctx);
|
||||
|
||||
std::array<int, 256> audio_handles {};
|
||||
size_t audio_handles_num = 0;
|
||||
|
||||
g_audioout2_port_mutex.Lock();
|
||||
for (auto& port_state: g_audioout2_ports) {
|
||||
if (port_state.used && port_state.context == ctx) {
|
||||
if (port_state.audio_handle > 0 && audio_handles_num < audio_handles.size()) {
|
||||
audio_handles[audio_handles_num++] = port_state.audio_handle;
|
||||
}
|
||||
port_state = AudioOut2PortStateEntry {};
|
||||
}
|
||||
}
|
||||
g_audioout2_port_mutex.Unlock();
|
||||
|
||||
for (size_t i = 0; i < audio_handles_num; i++) {
|
||||
audioout2_close_audio_handle(audio_handles[i]);
|
||||
}
|
||||
|
||||
g_audioout2_context_mutex.Lock();
|
||||
if (auto* state = audioout2_find_context_locked(ctx); state != nullptr) {
|
||||
*state = AudioOut2ContextState {};
|
||||
}
|
||||
g_audioout2_context_mutex.Unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2ContextSetAttributes(AudioOut2ContextHandle ctx,
|
||||
const AudioOut2Attribute* attributes,
|
||||
uint32_t num) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t ctx = 0x%016" PRIx64 ", num = %" PRIu32 "\n", ctx, num);
|
||||
EXIT_NOT_IMPLEMENTED(num != 0 && attributes == nullptr);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2ContextAdvance(AudioOut2ContextHandle ctx) {
|
||||
g_audioout2_context_mutex.Lock();
|
||||
if (auto* state = audioout2_find_context_locked(ctx); state != nullptr) {
|
||||
audioout2_update_context_locked(state);
|
||||
}
|
||||
g_audioout2_context_mutex.Unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2ContextPush(AudioOut2ContextHandle ctx, uint32_t blocking) {
|
||||
uint32_t sleep_micros = audioout2_grain_micros(512);
|
||||
|
||||
for (;;) {
|
||||
g_audioout2_context_mutex.Lock();
|
||||
if (auto* state = audioout2_find_context_locked(ctx); state != nullptr) {
|
||||
audioout2_update_context_locked(state);
|
||||
sleep_micros = audioout2_grain_micros(state->num_grains);
|
||||
if (state->queued < state->queue_depth) {
|
||||
if (state->queued == 0) {
|
||||
state->last_update = LibKernel::KernelGetProcessTime();
|
||||
}
|
||||
state->queued++;
|
||||
g_audioout2_context_mutex.Unlock();
|
||||
audioout2_queue_context_audio(ctx);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
g_audioout2_context_mutex.Unlock();
|
||||
|
||||
if (blocking == 0) {
|
||||
return AUDIO_OUT2_ERROR_NOT_READY;
|
||||
}
|
||||
|
||||
Common::Thread::SleepMicro(sleep_micros);
|
||||
}
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2ContextGetQueueLevel(AudioOut2ContextHandle ctx, uint32_t* queue_level,
|
||||
uint32_t* available_queues) {
|
||||
if (queue_level != nullptr) {
|
||||
*queue_level = 0;
|
||||
}
|
||||
if (available_queues != nullptr) {
|
||||
*available_queues = 4;
|
||||
}
|
||||
|
||||
g_audioout2_context_mutex.Lock();
|
||||
if (auto* state = audioout2_find_context_locked(ctx); state != nullptr) {
|
||||
audioout2_update_context_locked(state);
|
||||
if (queue_level != nullptr) {
|
||||
*queue_level = state->queued;
|
||||
}
|
||||
if (available_queues != nullptr) {
|
||||
*available_queues =
|
||||
(state->queued < state->queue_depth ? state->queue_depth - state->queued : 0);
|
||||
}
|
||||
}
|
||||
g_audioout2_context_mutex.Unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2PortCreate(AudioOut2ContextHandle ctx, const AudioOut2PortParam* params,
|
||||
AudioOut2PortHandle* port) {
|
||||
EXIT_NOT_IMPLEMENTED(params == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(port == nullptr);
|
||||
|
||||
const auto next_port = g_audioout2_next_port.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
g_audioout2_port_mutex.Lock();
|
||||
auto* port_state = audioout2_find_port_locked(0);
|
||||
if (port_state == nullptr) {
|
||||
for (auto& candidate: g_audioout2_ports) {
|
||||
if (!candidate.used) {
|
||||
port_state = &candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_audioout2_port_mutex.Unlock();
|
||||
|
||||
if (next_port > g_audioout2_ports.size() || port_state == nullptr) {
|
||||
return AUDIO_OUT2_ERROR_PORT_FULL;
|
||||
}
|
||||
|
||||
*port = next_port;
|
||||
|
||||
const auto samples_num = audioout2_context_grains(ctx);
|
||||
const auto audio_format = audioout2_data_format_to_audio_format(params->data_format);
|
||||
const auto audio_type = audioout2_port_type_to_audio_out_type(params->port_type);
|
||||
int audio_handle = 0;
|
||||
|
||||
if (audio_format != AudioInternal::Format::Unknown &&
|
||||
!audioout2_port_type_is_object(params->port_type)) {
|
||||
audio_handle = AudioInternal::AudioOutOpen(audio_type, samples_num, params->sampling_freq,
|
||||
audio_format);
|
||||
}
|
||||
|
||||
g_audioout2_port_mutex.Lock();
|
||||
*port_state = AudioOut2PortStateEntry {};
|
||||
port_state->used = true;
|
||||
port_state->handle = *port;
|
||||
port_state->context = ctx;
|
||||
port_state->port_type = params->port_type;
|
||||
port_state->data_format = params->data_format;
|
||||
port_state->sampling_freq = params->sampling_freq;
|
||||
port_state->samples_num = samples_num;
|
||||
port_state->audio_format = audio_format;
|
||||
port_state->audio_handle = audio_handle;
|
||||
g_audioout2_port_mutex.Unlock();
|
||||
|
||||
if (next_port <= 16 || (next_port % 600) == 0) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t ctx = 0x%016" PRIx64 "\n"
|
||||
"\t port = 0x%016" PRIx64 "\n"
|
||||
"\t port_type = %" PRIu16 "\n"
|
||||
"\t data_format = 0x%08" PRIx32 "\n"
|
||||
"\t sampling_freq = %" PRIu32 "\n",
|
||||
ctx, *port, params->port_type, params->data_format, params->sampling_freq);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2PortDestroy(AudioOut2PortHandle port) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t port = 0x%016" PRIx64 "\n", port);
|
||||
|
||||
int audio_handle = 0;
|
||||
g_audioout2_port_mutex.Lock();
|
||||
if (auto* state = audioout2_find_port_locked(port); state != nullptr) {
|
||||
audio_handle = state->audio_handle;
|
||||
*state = AudioOut2PortStateEntry {};
|
||||
}
|
||||
g_audioout2_port_mutex.Unlock();
|
||||
|
||||
audioout2_close_audio_handle(audio_handle);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2PortSetAttributes(AudioOut2PortHandle port,
|
||||
const AudioOut2Attribute* attributes, uint32_t num) {
|
||||
EXIT_NOT_IMPLEMENTED(num != 0 && attributes == nullptr);
|
||||
|
||||
const void* pcm_data = nullptr;
|
||||
bool has_pcm = false;
|
||||
for (uint32_t i = 0; i < num; i++) {
|
||||
if (attributes[i].attribute_id == AUDIO_OUT2_PORT_ATTRIBUTE_ID_PCM &&
|
||||
attributes[i].value != nullptr && attributes[i].value_size >= sizeof(AudioOut2Pcm)) {
|
||||
AudioOut2Pcm pcm {};
|
||||
std::memcpy(&pcm, attributes[i].value, sizeof(AudioOut2Pcm));
|
||||
pcm_data = pcm.data;
|
||||
has_pcm = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_pcm) {
|
||||
g_audioout2_port_mutex.Lock();
|
||||
if (auto* state = audioout2_find_port_locked(port); state != nullptr) {
|
||||
state->pcm_data = pcm_data;
|
||||
}
|
||||
g_audioout2_port_mutex.Unlock();
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2PortGetState(AudioOut2PortHandle port, AudioOut2PortState* state) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(state == nullptr);
|
||||
|
||||
std::memset(state, 0, sizeof(AudioOut2PortState));
|
||||
state->output = 1;
|
||||
state->num_channels = 2;
|
||||
state->volume = 127;
|
||||
state->reroute_counter = 0;
|
||||
state->flags = 0;
|
||||
|
||||
g_audioout2_port_mutex.Lock();
|
||||
if (auto* port_state = audioout2_find_port_locked(port); port_state != nullptr) {
|
||||
state->num_channels = audioout2_data_format_channels(port_state->data_format);
|
||||
}
|
||||
g_audioout2_port_mutex.Unlock();
|
||||
|
||||
// LOGF("\t port = 0x%016" PRIx64 "\n", port);
|
||||
// LOGF("\t num_channels = %" PRIu8 "\n", state->num_channels);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2GetSystemState(AudioOut2SystemState* state) {
|
||||
PRINT_NAME();
|
||||
EXIT_NOT_IMPLEMENTED(state == nullptr);
|
||||
std::memset(state, 0, sizeof(AudioOut2SystemState));
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2UserCreate(uint32_t user_id, AudioOut2UserHandle* handle) {
|
||||
PRINT_NAME();
|
||||
EXIT_NOT_IMPLEMENTED(handle == nullptr);
|
||||
*handle = static_cast<AudioOut2UserHandle>(
|
||||
g_audioout2_next_user.fetch_add(1, std::memory_order_relaxed));
|
||||
LOGF("\t user_id = %" PRIu32 ", handle = 0x%016" PRIx64 "\n", user_id,
|
||||
static_cast<uint64_t>(*handle));
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2UserDestroy(AudioOut2UserHandle handle) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t handle = 0x%016" PRIx64 "\n", static_cast<uint64_t>(handle));
|
||||
return OK;
|
||||
}
|
||||
|
||||
size_t KYTY_SYSV_ABI AudioOut2GetSpeakerArrayMemorySize(uint32_t num_speakers, uint8_t is_3d,
|
||||
uint8_t is_ambisonics) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto speakers = std::clamp<uint32_t>(num_speakers, 1, 32);
|
||||
const auto size = static_cast<size_t>(0x400 + speakers * (is_ambisonics != 0 ? 0x100 : 0x40) +
|
||||
(is_3d != 0 ? 0x200 : 0));
|
||||
|
||||
LOGF("\t num_speakers = %" PRIu32 "\n"
|
||||
"\t is_3d = %" PRIu8 "\n"
|
||||
"\t is_ambisonics = %" PRIu8 "\n"
|
||||
"\t memory_size = 0x%016" PRIx64 "\n",
|
||||
num_speakers, is_3d, is_ambisonics, static_cast<uint64_t>(size));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2SpeakerArrayCreate(AudioOut2SpeakerArrayHandle* handle,
|
||||
const void* vbap_params, const void* ambi_params) {
|
||||
PRINT_NAME();
|
||||
EXIT_NOT_IMPLEMENTED(handle == nullptr);
|
||||
|
||||
*handle = nullptr;
|
||||
|
||||
g_audioout2_speaker_array_mutex.Lock();
|
||||
for (auto& state: g_audioout2_speaker_arrays) {
|
||||
if (!state.used) {
|
||||
state = AudioOut2SpeakerArrayState {};
|
||||
state.used = true;
|
||||
state.handle = &state;
|
||||
state.num_speakers = 2;
|
||||
*handle = state.handle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_audioout2_speaker_array_mutex.Unlock();
|
||||
|
||||
LOGF("\t handle = 0x%016" PRIx64 "\n"
|
||||
"\t vbap_params = 0x%016" PRIx64 "\n"
|
||||
"\t ambi_params = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(*handle), reinterpret_cast<uint64_t>(vbap_params),
|
||||
reinterpret_cast<uint64_t>(ambi_params));
|
||||
|
||||
return (*handle != nullptr ? OK : AUDIO_OUT2_ERROR_PORT_FULL);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2SpeakerArrayDestroy(AudioOut2SpeakerArrayHandle handle) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t handle = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(handle));
|
||||
|
||||
g_audioout2_speaker_array_mutex.Lock();
|
||||
for (auto& state: g_audioout2_speaker_arrays) {
|
||||
if (state.used && state.handle == handle) {
|
||||
state = AudioOut2SpeakerArrayState {};
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_audioout2_speaker_array_mutex.Unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2GetSpeakerArrayCoefficients(
|
||||
AudioOut2SpeakerArrayHandle handle, AudioOut2Position pos, float spread, float* coefficients,
|
||||
uint32_t num_coefficients, uint8_t height_aware, float downmix_spread_radius) {
|
||||
PRINT_NAME();
|
||||
EXIT_NOT_IMPLEMENTED(coefficients == nullptr && num_coefficients != 0);
|
||||
|
||||
if (coefficients != nullptr) {
|
||||
std::fill(coefficients, coefficients + num_coefficients, 0.0f);
|
||||
if (num_coefficients > 0) {
|
||||
coefficients[0] = 1.0f;
|
||||
}
|
||||
if (num_coefficients > 1) {
|
||||
coefficients[1] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
LOGF("\t handle = 0x%016" PRIx64 ", coeffs = %" PRIu32
|
||||
", pos = (%f, %f, %f), spread = %f, height = %" PRIu8 ", downmix = %f\n",
|
||||
reinterpret_cast<uint64_t>(handle), num_coefficients, static_cast<double>(pos.x),
|
||||
static_cast<double>(pos.y), static_cast<double>(pos.z), static_cast<double>(spread),
|
||||
height_aware, static_cast<double>(downmix_spread_radius));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2GetSpeakerArrayAmbisonicsCoefficients(AudioOut2SpeakerArrayHandle handle,
|
||||
uint32_t ambisonics_channel,
|
||||
float* coefficients,
|
||||
uint32_t num_coefficients) {
|
||||
PRINT_NAME();
|
||||
EXIT_NOT_IMPLEMENTED(coefficients == nullptr && num_coefficients != 0);
|
||||
|
||||
if (coefficients != nullptr) {
|
||||
std::fill(coefficients, coefficients + num_coefficients, 0.0f);
|
||||
if (num_coefficients > 0) {
|
||||
coefficients[0] =
|
||||
(ambisonics_channel == 0 || ambisonics_channel == 64 ? 0.70710677f : 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
LOGF("\t handle = 0x%016" PRIx64 ", channel = %" PRIu32 ", coeffs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(handle), ambisonics_channel, num_coefficients);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2GetSpeakerInfo(AudioOut2SpeakerInfo* info, uint32_t flags) {
|
||||
EXIT_NOT_IMPLEMENTED(info == nullptr);
|
||||
std::memset(info, 0, sizeof(AudioOut2SpeakerInfo));
|
||||
info->type = 0;
|
||||
info->available_bits = 0x03;
|
||||
info->flags = 0;
|
||||
info->speaker_angle[0] = {-30, 0};
|
||||
info->speaker_angle[1] = {30, 0};
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2SetSystemDebugState(const AudioOut2SystemDebugStateParam* param) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(param));
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2Set3DLatency(uint32_t user_id, uint32_t output, uint32_t latency_us) {
|
||||
// Not sure
|
||||
|
||||
PRINT_NAME();
|
||||
LOGF("\t user_id = %" PRIu32 ", output = %" PRIu32 ", latency_us = %" PRIu32 "\n", user_id,
|
||||
output, latency_us);
|
||||
|
||||
if (output > AUDIO_OUT2_MASTERING_OUTPUT_RECORDING) {
|
||||
return AUDIO_OUT2_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
g_audioout2_latency_mutex.Lock();
|
||||
AudioOut2LatencyState* free_state = nullptr;
|
||||
for (auto& state: g_audioout2_latencies) {
|
||||
if (state.used && state.user_id == user_id && state.output == output) {
|
||||
state.latency_us = latency_us;
|
||||
g_audioout2_latency_mutex.Unlock();
|
||||
return OK;
|
||||
}
|
||||
if (!state.used && free_state == nullptr) {
|
||||
free_state = &state;
|
||||
}
|
||||
}
|
||||
|
||||
if (free_state != nullptr) {
|
||||
*free_state = AudioOut2LatencyState {true, user_id, output, latency_us};
|
||||
}
|
||||
g_audioout2_latency_mutex.Unlock();
|
||||
|
||||
return (free_state != nullptr ? OK : AUDIO_OUT2_ERROR_PORT_FULL);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2MasteringInit(uint32_t flags) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t flags = 0x%08" PRIx32 "\n", flags);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2MasteringSetParam(const AudioOut2MasteringParamsHeader* param,
|
||||
uint32_t output, uint32_t flags) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t param = 0x%016" PRIx64 ", output = %" PRIu32 ", flags = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(param), output, flags);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2MasteringGetState(AudioOut2MasteringStatesHeader* state, uint32_t output,
|
||||
AudioOut2UserHandle user) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t state = 0x%016" PRIx64 ", output = %" PRIu32 ", user = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(state), output, static_cast<uint64_t>(user));
|
||||
|
||||
if (state == nullptr) {
|
||||
return AUDIO_OUT2_ERROR_MASTERING_INVALID_API_PARAM;
|
||||
}
|
||||
|
||||
const auto states_id = state->states_id;
|
||||
switch (states_id) {
|
||||
case AUDIO_OUT2_MASTERING_STATES_ID_DEFAULT: {
|
||||
auto* full_state = reinterpret_cast<AudioOut2MasteringStates*>(state);
|
||||
std::memset(full_state, 0, sizeof(AudioOut2MasteringStates));
|
||||
full_state->states_header.states_id = AUDIO_OUT2_MASTERING_STATES_ID_DEFAULT;
|
||||
full_state->compressor_states.descriptor.id =
|
||||
AUDIO_OUT2_MASTERING_STATES_STRUCT_ID_COMPRESSOR_DEFAULT;
|
||||
full_state->compressor_states.descriptor.size =
|
||||
sizeof(AudioOut2MasteringCompressorStates);
|
||||
full_state->limiter_states.descriptor.id =
|
||||
AUDIO_OUT2_MASTERING_STATES_STRUCT_ID_LIMITER_DEFAULT;
|
||||
full_state->limiter_states.descriptor.size = sizeof(AudioOut2MasteringLimiterStates);
|
||||
return OK;
|
||||
}
|
||||
case AUDIO_OUT2_MASTERING_STATES_ID_V2: {
|
||||
auto* full_state = reinterpret_cast<AudioOut2MasteringStatesV2*>(state);
|
||||
std::memset(full_state, 0, sizeof(AudioOut2MasteringStatesV2));
|
||||
full_state->states_header.states_id = AUDIO_OUT2_MASTERING_STATES_ID_V2;
|
||||
full_state->compressor_states.descriptor.id =
|
||||
AUDIO_OUT2_MASTERING_STATES_STRUCT_ID_COMPRESSOR_V2;
|
||||
full_state->compressor_states.descriptor.size =
|
||||
sizeof(AudioOut2MasteringCompressorStatesV2);
|
||||
full_state->limiter_states.descriptor.id =
|
||||
AUDIO_OUT2_MASTERING_STATES_STRUCT_ID_LIMITER_DEFAULT;
|
||||
full_state->limiter_states.descriptor.size = sizeof(AudioOut2MasteringLimiterStates);
|
||||
return OK;
|
||||
}
|
||||
default: return AUDIO_OUT2_ERROR_MASTERING_INVALID_STATES_ID;
|
||||
}
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AudioOut2MasteringTerm() {
|
||||
PRINT_NAME();
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace AudioOut2
|
||||
} // namespace Libs::Audio
|
||||
@@ -0,0 +1,898 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "graphics/host_gpu/hostMemory.h"
|
||||
#include "kernel/pthread.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/guestPrintf.h"
|
||||
#include "libs/libs.h"
|
||||
#include "libs/vaContext.h"
|
||||
#include "loader/runtimeLinker.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <cinttypes>
|
||||
#include <cmath>
|
||||
#include <condition_variable>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <fmt/format.h>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibKernel {
|
||||
void KernelDispatchPendingSignalForCurrentThread();
|
||||
} // namespace LibKernel
|
||||
|
||||
namespace LibC {
|
||||
|
||||
LIB_VERSION("libc", 1, "libc", 1, 1);
|
||||
|
||||
static uint32_t g_need_flag = 1;
|
||||
|
||||
using cxa_destructor_func_t = KYTY_SYSV_ABI void (*)(void*);
|
||||
using atexit_func_t = KYTY_SYSV_ABI void (*)();
|
||||
|
||||
struct CxaDestructor {
|
||||
cxa_destructor_func_t destructor_func;
|
||||
void* destructor_object;
|
||||
void* module_id;
|
||||
};
|
||||
|
||||
struct CContext {
|
||||
std::list<CxaDestructor> cxa;
|
||||
std::list<atexit_func_t> atexit;
|
||||
};
|
||||
|
||||
struct InitEnvParams {
|
||||
int argc;
|
||||
uint32_t pad;
|
||||
const char* argv[3];
|
||||
};
|
||||
|
||||
static int g_argc = 0;
|
||||
static const char* const* g_argv = nullptr;
|
||||
static const char* const* g_envp = nullptr;
|
||||
|
||||
int GetArgc() {
|
||||
return g_argc;
|
||||
}
|
||||
|
||||
const char** GetArgv() {
|
||||
return const_cast<const char**>(g_argv);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI void exit(int code) {
|
||||
PRINT_NAME();
|
||||
|
||||
::exit(code);
|
||||
}
|
||||
|
||||
static void PrintAbortStringCandidate(const char* name, uint64_t addr) {
|
||||
if (!Graphics::HostMemoryIsReadable(addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* ptr = reinterpret_cast<const char*>(static_cast<uintptr_t>(addr));
|
||||
char buf[257] {};
|
||||
size_t len = 0;
|
||||
|
||||
for (; len < sizeof(buf) - 1 && Graphics::HostMemoryIsReadable(addr + len); len++) {
|
||||
const auto c = static_cast<unsigned char>(ptr[len]);
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
if (!std::isprint(c) && c != '\n' && c != '\r' && c != '\t') {
|
||||
return;
|
||||
}
|
||||
buf[len] = static_cast<char>(c);
|
||||
}
|
||||
|
||||
if (len >= 4) {
|
||||
LOGF("\t %s string = \"%s\"\n", name, buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintAbortWideStringCandidate(const char* name, uint64_t addr) {
|
||||
if (!Graphics::HostMemoryIsReadable(addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* ptr = reinterpret_cast<const uint16_t*>(static_cast<uintptr_t>(addr));
|
||||
char buf[257] {};
|
||||
size_t len = 0;
|
||||
|
||||
for (;
|
||||
len < sizeof(buf) - 1 && Graphics::HostMemoryIsReadable(addr + len * sizeof(uint16_t) + 1);
|
||||
len++) {
|
||||
const auto c = ptr[len];
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
if (c > 0x7f ||
|
||||
(!std::isprint(static_cast<unsigned char>(c)) && c != '\n' && c != '\r' && c != '\t')) {
|
||||
return;
|
||||
}
|
||||
buf[len] = static_cast<char>(c);
|
||||
}
|
||||
|
||||
if (len >= 4) {
|
||||
LOGF("\t %s u16 = \"%s\"\n", name, buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintAbortBytesCandidate(const char* name, uint64_t addr) {
|
||||
if (!Graphics::HostMemoryIsReadable(addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t bytes[64] {};
|
||||
size_t len = 0;
|
||||
|
||||
for (; len < sizeof(bytes) && Graphics::HostMemoryIsReadable(addr + len); len++) {
|
||||
bytes[len] = *reinterpret_cast<const uint8_t*>(static_cast<uintptr_t>(addr + len));
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGF("\t %s bytes =", name);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
LOGF(" %02" PRIx8, bytes[i]);
|
||||
}
|
||||
LOGF("\n");
|
||||
}
|
||||
|
||||
static void PrintAbortPointerCandidate(const char* name, uint64_t addr) {
|
||||
PrintAbortStringCandidate(name, addr);
|
||||
PrintAbortWideStringCandidate(name, addr);
|
||||
PrintAbortBytesCandidate(name, addr);
|
||||
}
|
||||
|
||||
static bool LooksLikeAbortPointer(uint64_t addr) {
|
||||
return Graphics::HostMemoryIsReadable(addr) && addr >= 0x10000;
|
||||
}
|
||||
|
||||
static void PrintAbortPointerArrayCandidate(const char* name, uint64_t addr) {
|
||||
if (!LooksLikeAbortPointer(addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const auto slot_addr = addr + static_cast<uint64_t>(i) * sizeof(uint64_t);
|
||||
if (!Graphics::HostMemoryIsReadable(slot_addr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const auto value = *reinterpret_cast<const uint64_t*>(static_cast<uintptr_t>(slot_addr));
|
||||
if (!LooksLikeAbortPointer(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGF("\t %s[%d] = 0x%016" PRIx64 "\n", name, i, value);
|
||||
const auto child_name = fmt::format("{}[{}]", name, i);
|
||||
PrintAbortPointerCandidate(child_name.c_str(), value);
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]] static KYTY_SYSV_ABI void abort(uint64_t arg0, uint64_t arg1, uint64_t arg2,
|
||||
uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
||||
PRINT_NAME();
|
||||
|
||||
uint64_t rbp = 0;
|
||||
uint64_t rsp = 0;
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
asm volatile("movq %%rbp, %0" : "=r"(rbp));
|
||||
asm volatile("movq %%rsp, %0" : "=r"(rsp));
|
||||
#endif
|
||||
|
||||
const auto ret = reinterpret_cast<uint64_t>(__builtin_return_address(0));
|
||||
|
||||
LOGF("Guest abort diagnostics:\n"
|
||||
"\t return = 0x%016" PRIx64 "\n"
|
||||
"\t rbp = 0x%016" PRIx64 "\n"
|
||||
"\t rsp = 0x%016" PRIx64 "\n"
|
||||
"\t arg0 = 0x%016" PRIx64 "\n"
|
||||
"\t arg1 = 0x%016" PRIx64 "\n"
|
||||
"\t arg2 = 0x%016" PRIx64 "\n"
|
||||
"\t arg3 = 0x%016" PRIx64 "\n"
|
||||
"\t arg4 = 0x%016" PRIx64 "\n"
|
||||
"\t arg5 = 0x%016" PRIx64 "\n",
|
||||
ret, rbp, rsp, arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
|
||||
PrintAbortPointerCandidate("arg0", arg0);
|
||||
PrintAbortPointerCandidate("arg1", arg1);
|
||||
PrintAbortPointerCandidate("arg2", arg2);
|
||||
PrintAbortPointerCandidate("arg3", arg3);
|
||||
PrintAbortPointerCandidate("arg4", arg4);
|
||||
PrintAbortPointerCandidate("arg5", arg5);
|
||||
PrintAbortPointerArrayCandidate("arg0", arg0);
|
||||
PrintAbortPointerArrayCandidate("arg1", arg1);
|
||||
PrintAbortPointerArrayCandidate("arg2", arg2);
|
||||
PrintAbortPointerArrayCandidate("arg3", arg3);
|
||||
PrintAbortPointerArrayCandidate("arg4", arg4);
|
||||
PrintAbortPointerArrayCandidate("arg5", arg5);
|
||||
|
||||
if (rbp != 0) {
|
||||
Common::Singleton<Loader::RuntimeLinker>::Instance()->StackTrace(rbp);
|
||||
}
|
||||
|
||||
if (rsp != 0) {
|
||||
LOGF("Guest abort stack words:\n");
|
||||
auto* linker = Common::Singleton<Loader::RuntimeLinker>::Instance();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
const auto addr = rsp + static_cast<uint64_t>(i) * sizeof(uint64_t);
|
||||
if (!Graphics::HostMemoryIsReadable(addr)) {
|
||||
break;
|
||||
}
|
||||
const auto value = *reinterpret_cast<const uint64_t*>(static_cast<uintptr_t>(addr));
|
||||
auto* program = linker->FindProgramByAddr(value);
|
||||
if (program != nullptr) {
|
||||
auto module_name = Common::PathToString(program->file_name.filename());
|
||||
LOGF("\t [%02d] 0x%016" PRIx64 " %s+0x%016" PRIx64 "\n", i, value,
|
||||
module_name.c_str(), value - program->base_vaddr);
|
||||
} else {
|
||||
LOGF("\t [%02d] 0x%016" PRIx64 "\n", i, value);
|
||||
}
|
||||
PrintAbortPointerCandidate(fmt::format("stack[{:02d}]", i).c_str(), value);
|
||||
PrintAbortPointerArrayCandidate(fmt::format("stack[{:02d}]", i).c_str(), value);
|
||||
}
|
||||
}
|
||||
|
||||
EXIT("Guest abort()\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int* libc_error() {
|
||||
PRINT_NAME();
|
||||
|
||||
return Posix::GetErrorAddr();
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI void init_env(const InitEnvParams* params) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (params == nullptr) {
|
||||
g_argc = 0;
|
||||
g_argv = nullptr;
|
||||
g_envp = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr int argv_capacity = static_cast<int>(sizeof(params->argv) / sizeof(params->argv[0]));
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(params->argc < 0 || params->argc >= argv_capacity);
|
||||
|
||||
g_argc = params->argc;
|
||||
g_argv = params->argv;
|
||||
g_envp = params->argv + params->argc + 1;
|
||||
|
||||
LOGF("\t argc = %d\n"
|
||||
"\t argv = 0x%016" PRIx64 "\n"
|
||||
"\t envp = 0x%016" PRIx64 "\n",
|
||||
g_argc, reinterpret_cast<uint64_t>(g_argv), reinterpret_cast<uint64_t>(g_envp));
|
||||
|
||||
for (int i = 0; i < g_argc; i++) {
|
||||
LOGF("\t argv[%d] = %s\n", i, g_argv[i] != nullptr ? g_argv[i] : "<null>");
|
||||
}
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int atexit(atexit_func_t func) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (func != nullptr) {
|
||||
Common::Singleton<CContext>::Instance()->atexit.push_front(func);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int libc_printf(VA_ARGS) {
|
||||
VA_CONTEXT(ctx); // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
|
||||
PRINT_NAME();
|
||||
|
||||
return GetGuestPrintfCtxFunc()(&ctx);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int puts(const char* s) {
|
||||
PRINT_NAME();
|
||||
|
||||
return GetGuestPrintfStdFunc()("%s\n", s);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int setenv(const char* name, const char* value, int overwrite) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t name = %s\n"
|
||||
"\t value = %s\n"
|
||||
"\t overwrite = %d\n",
|
||||
(name != nullptr ? name : "<null>"), (value != nullptr ? value : "<null>"), overwrite);
|
||||
|
||||
if (name == nullptr || value == nullptr || name[0] == '\0' ||
|
||||
std::strchr(name, '=') != nullptr) {
|
||||
*Posix::GetErrorAddr() = Posix::POSIX_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (overwrite == 0 && std::getenv(name) != nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
const auto ret = ::_putenv_s(name, value);
|
||||
if (ret != 0) {
|
||||
*Posix::GetErrorAddr() = ret;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
const auto ret = ::setenv(name, value, overwrite);
|
||||
if (ret != 0) {
|
||||
*Posix::GetErrorAddr() = errno;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int64_t libc_time(int64_t* timer) {
|
||||
const auto now = static_cast<int64_t>(std::time(nullptr));
|
||||
if (timer != nullptr) {
|
||||
*timer = now;
|
||||
}
|
||||
return now;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI double libc_difftime(int64_t time1, int64_t time0) {
|
||||
return std::difftime(static_cast<std::time_t>(time1), static_cast<std::time_t>(time0));
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI std::tm* libc_gmtime(const int64_t* timer) {
|
||||
if (timer == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
thread_local std::tm result {};
|
||||
const auto t = static_cast<std::time_t>(*timer);
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
if (_gmtime64_s(&result, &t) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
if (gmtime_r(&t, &result) == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI std::tm* libc_localtime(const int64_t* timer) {
|
||||
if (timer == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
thread_local std::tm result {};
|
||||
const auto t = static_cast<std::time_t>(*timer);
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
if (_localtime64_s(&result, &t) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
if (localtime_r(&t, &result) == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int64_t libc_mktime(std::tm* timeptr) {
|
||||
if (timeptr == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
return static_cast<int64_t>(_mktime64(timeptr));
|
||||
#else
|
||||
return static_cast<int64_t>(std::mktime(timeptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI size_t libc_strftime(char* str, size_t count, const char* format,
|
||||
const std::tm* timeptr) {
|
||||
if (str == nullptr || format == nullptr || timeptr == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::strftime(str, count, format, timeptr);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI void catchReturnFromMain(int status) {
|
||||
PRINT_NAME();
|
||||
|
||||
uint64_t ret_addr = reinterpret_cast<uint64_t>(__builtin_return_address(0));
|
||||
uint64_t rsp = 0;
|
||||
uint64_t rbp = 0;
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
asm volatile("movq %%rsp, %0\n\t"
|
||||
"movq %%rbp, %1\n\t"
|
||||
: "=r"(rsp), "=r"(rbp));
|
||||
#endif
|
||||
|
||||
LOGF("\t status = %d\n"
|
||||
"\t ret_addr = 0x%016" PRIx64 "\n"
|
||||
"\t rsp = 0x%016" PRIx64 "\n"
|
||||
"\t rbp = 0x%016" PRIx64 "\n",
|
||||
status, ret_addr, rsp, rbp);
|
||||
if (rsp != 0) {
|
||||
auto* stack = reinterpret_cast<const uint64_t*>(rsp);
|
||||
for (uint32_t i = 0; i < 12; i++) {
|
||||
LOGF("\t stack[%02" PRIu32 "] = 0x%016" PRIx64 "\n", i, stack[i]);
|
||||
}
|
||||
}
|
||||
|
||||
::printf("return from main = %d\n", status);
|
||||
}
|
||||
|
||||
enum class ThrdResult : int {
|
||||
Success = 0,
|
||||
NoMem = 1,
|
||||
TimedOut = 2,
|
||||
Busy = 3,
|
||||
Error = 4,
|
||||
Perm = 5,
|
||||
};
|
||||
|
||||
static int mtx_result(int result) {
|
||||
return (result == OK ? static_cast<int>(ThrdResult::Success)
|
||||
: static_cast<int>(ThrdResult::Error));
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int MtxInit(LibKernel::PthreadMutex* mtx, int type) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mtx == nullptr) {
|
||||
return static_cast<int>(ThrdResult::Error);
|
||||
}
|
||||
|
||||
constexpr int mtx_recursive = 0x100;
|
||||
if ((type & mtx_recursive) == 0) {
|
||||
return mtx_result(LibKernel::PthreadMutexInit(mtx, nullptr));
|
||||
}
|
||||
|
||||
LibKernel::PthreadMutexattr attr = nullptr;
|
||||
int result = LibKernel::PthreadMutexattrInit(&attr);
|
||||
result = (result == OK ? LibKernel::PthreadMutexattrSettype(&attr, 2) : result);
|
||||
result = (result == OK ? LibKernel::PthreadMutexInit(mtx, &attr) : result);
|
||||
(void)LibKernel::PthreadMutexattrDestroy(&attr);
|
||||
|
||||
return mtx_result(result);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int MtxInitWithName(LibKernel::PthreadMutex* mtx, int type,
|
||||
const char* /*name*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
return MtxInit(mtx, type);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int MtxInitWithDefaultNameOverride(LibKernel::PthreadMutex* mtx, int type,
|
||||
const char* /*name*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
return MtxInit(mtx, type);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI void MtxDestroy(LibKernel::PthreadMutex* mtx) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mtx != nullptr) {
|
||||
(void)LibKernel::PthreadMutexDestroy(mtx);
|
||||
}
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int MtxLock(LibKernel::PthreadMutex* mtx) {
|
||||
PRINT_NAME();
|
||||
|
||||
return mtx_result(LibKernel::PthreadMutexLock(mtx));
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int MtxTrylock(LibKernel::PthreadMutex* mtx) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto result = LibKernel::PthreadMutexTrylock(mtx);
|
||||
if (result == OK) {
|
||||
return static_cast<int>(ThrdResult::Success);
|
||||
}
|
||||
return static_cast<int>(ThrdResult::Busy);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int MtxTimedlock(LibKernel::PthreadMutex* mtx, const void* /*xtime*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
return mtx_result(LibKernel::PthreadMutexLock(mtx));
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int MtxUnlock(LibKernel::PthreadMutex* mtx) {
|
||||
PRINT_NAME();
|
||||
|
||||
return mtx_result(LibKernel::PthreadMutexUnlock(mtx));
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int MtxCurrentOwns(LibKernel::PthreadMutex* /*mtx*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
using execute_once_func_t = KYTY_SYSV_ABI int (*)(void*, void*, void**);
|
||||
|
||||
static std::mutex g_execute_once_mutex;
|
||||
static std::condition_variable g_execute_once_cv;
|
||||
|
||||
static KYTY_SYSV_ABI int std_execute_once(int* flag, execute_once_func_t func, void* arg) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (flag == nullptr || func == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr int once_init = 0;
|
||||
constexpr int once_done = 1;
|
||||
constexpr int once_running = 2;
|
||||
|
||||
{
|
||||
std::unique_lock lock(g_execute_once_mutex);
|
||||
while (*flag == once_running) {
|
||||
g_execute_once_cv.wait_for(lock, std::chrono::microseconds(10000));
|
||||
if (*flag == once_running) {
|
||||
lock.unlock();
|
||||
LibKernel::KernelDispatchPendingSignalForCurrentThread();
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
if (*flag == once_done) {
|
||||
return 1;
|
||||
}
|
||||
*flag = once_running;
|
||||
}
|
||||
|
||||
void* callback_context = nullptr;
|
||||
int result = func(nullptr, arg, &callback_context);
|
||||
|
||||
{
|
||||
std::lock_guard lock(g_execute_once_mutex);
|
||||
*flag = (result != 0 ? once_done : once_init);
|
||||
}
|
||||
g_execute_once_cv.notify_all();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int cxa_atexit(cxa_destructor_func_t func, void* arg, void* d) {
|
||||
PRINT_NAME();
|
||||
|
||||
auto* cc = Common::Singleton<CContext>::Instance();
|
||||
|
||||
CxaDestructor c {};
|
||||
c.destructor_func = func;
|
||||
c.destructor_object = arg;
|
||||
c.module_id = d;
|
||||
|
||||
cc->cxa.push_back(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KYTY_SYSV_ABI cxa_finalize(void* d) {
|
||||
PRINT_NAME();
|
||||
|
||||
auto* cc = Common::Singleton<CContext>::Instance();
|
||||
|
||||
for (auto i = cc->cxa.rbegin(); i != cc->cxa.rend(); ++i) {
|
||||
auto& c = *i;
|
||||
if ((d == nullptr || c.module_id == d) && c.destructor_func != nullptr) {
|
||||
auto* func = c.destructor_func;
|
||||
auto* object = c.destructor_object;
|
||||
c.destructor_func = nullptr;
|
||||
func(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace LibC
|
||||
|
||||
namespace LibcInternalExt {
|
||||
|
||||
LIB_VERSION("LibcInternalExt", 1, "LibcInternal", 1, 1);
|
||||
|
||||
static uint64_t g_mspace_atomic_id_mask = 0;
|
||||
static uint64_t g_mstate_table[64] = {0};
|
||||
|
||||
struct Info {
|
||||
uint64_t size;
|
||||
uint32_t unknown1;
|
||||
uint32_t unknown2;
|
||||
uint64_t* mspace_atomic_id_mask;
|
||||
uint64_t* mstate_table;
|
||||
};
|
||||
|
||||
void KYTY_SYSV_ABI LibcHeapGetTraceInfo(Info* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(info->size != 32);
|
||||
|
||||
info->mspace_atomic_id_mask = &g_mspace_atomic_id_mask;
|
||||
info->mstate_table = g_mstate_table;
|
||||
}
|
||||
|
||||
uint64_t KYTY_SYSV_ABI LibcInternalExtUnknownQBS714Jr3g(uint64_t arg0, uint64_t arg1, uint64_t arg2,
|
||||
uint64_t arg3, uint64_t arg4,
|
||||
uint64_t arg5) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t arg0 = 0x%016" PRIx64 "\n"
|
||||
"\t arg1 = 0x%016" PRIx64 "\n"
|
||||
"\t arg2 = 0x%016" PRIx64 "\n"
|
||||
"\t arg3 = 0x%016" PRIx64 "\n"
|
||||
"\t arg4 = 0x%016" PRIx64 "\n"
|
||||
"\t arg5 = 0x%016" PRIx64 "\n",
|
||||
arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitLibcInternalExt_1) {
|
||||
LIB_FUNC("NWtTN10cJzE", LibcInternalExt::LibcHeapGetTraceInfo);
|
||||
LIB_FUNC("qBS714-Jr3g", LibcInternalExt::LibcInternalExtUnknownQBS714Jr3g);
|
||||
}
|
||||
|
||||
} // namespace LibcInternalExt
|
||||
|
||||
namespace LibcInternal {
|
||||
|
||||
LIB_VERSION("LibcInternal", 1, "LibcInternal", 1, 1);
|
||||
|
||||
static uint32_t g_need_flag = 1;
|
||||
|
||||
int KYTY_SYSV_ABI vprintf(const char* str, VaList* c) {
|
||||
PRINT_NAME();
|
||||
|
||||
return GetGuestVprintfFunc()(str, c);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int snprintf(VA_ARGS) {
|
||||
VA_CONTEXT(ctx); // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
|
||||
PRINT_NAME();
|
||||
|
||||
return GetGuestSnprintfCtxFunc()(&ctx);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI fflush(FILE* stream) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(stream != stdout);
|
||||
|
||||
return ::fflush(stream);
|
||||
}
|
||||
|
||||
void* KYTY_SYSV_ABI memset(void* s, int c, size_t n) {
|
||||
PRINT_NAME();
|
||||
|
||||
return ::memset(s, c, n);
|
||||
}
|
||||
|
||||
void* KYTY_SYSV_ABI memcpy(void* dest, const void* src, size_t n) {
|
||||
return ::memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void* KYTY_SYSV_ABI memmove(void* dest, const void* src, size_t n) {
|
||||
return ::memmove(dest, src, n);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI memcmp(const void* s1, const void* s2, size_t n) {
|
||||
return ::memcmp(s1, s2, n);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI strcmp(const char* s1, const char* s2) {
|
||||
return ::strcmp(s1, s2);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI strncmp(const char* s1, const char* s2, size_t n) {
|
||||
return ::strncmp(s1, s2, n);
|
||||
}
|
||||
|
||||
size_t KYTY_SYSV_ABI strlen(const char* s) {
|
||||
return ::strlen(s);
|
||||
}
|
||||
|
||||
char* KYTY_SYSV_ABI strcpy(char* dest, const char* src) {
|
||||
return ::strcpy(dest, src);
|
||||
}
|
||||
|
||||
char* KYTY_SYSV_ABI strncpy(char* dest, const char* src, size_t count) {
|
||||
return ::strncpy(dest, src, count);
|
||||
}
|
||||
|
||||
char* KYTY_SYSV_ABI strcat(char* dest, const char* src) {
|
||||
return ::strcat(dest, src);
|
||||
}
|
||||
|
||||
const char* KYTY_SYSV_ABI strchr(const char* s, int c) {
|
||||
return ::strchr(s, c);
|
||||
}
|
||||
|
||||
char* KYTY_SYSV_ABI strrchr(const char* s, int c) {
|
||||
return const_cast<char*>(::strrchr(s, c));
|
||||
}
|
||||
|
||||
char* KYTY_SYSV_ABI strstr(const char* haystack, const char* needle) {
|
||||
static int log_count = 0;
|
||||
if (log_count++ < 8) {
|
||||
LOGF("LibcInternal::strstr(\"%s\", \"%s\")\n", (haystack != nullptr ? haystack : "<null>"),
|
||||
(needle != nullptr ? needle : "<null>"));
|
||||
}
|
||||
return const_cast<char*>(::strstr(haystack, needle));
|
||||
}
|
||||
|
||||
long KYTY_SYSV_ABI strtol(const char* str, char** endptr, int base) {
|
||||
static int log_count = 0;
|
||||
if (log_count++ < 16) {
|
||||
LOGF("LibcInternal::strtol(\"%s\", base=%d)\n", (str != nullptr ? str : "<null>"), base);
|
||||
}
|
||||
return ::strtol(str, endptr, base);
|
||||
}
|
||||
|
||||
unsigned long KYTY_SYSV_ABI strtoul(const char* str, char** endptr, int base) {
|
||||
static int log_count = 0;
|
||||
if (log_count++ < 16) {
|
||||
LOGF("LibcInternal::strtoul(\"%s\", base=%d)\n", (str != nullptr ? str : "<null>"), base);
|
||||
}
|
||||
return ::strtoul(str, endptr, base);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI atoi(const char* str) {
|
||||
return ::atoi(str);
|
||||
}
|
||||
|
||||
float KYTY_SYSV_ABI sinf(float x) {
|
||||
return std::sinf(x);
|
||||
}
|
||||
|
||||
float KYTY_SYSV_ABI cosf(float x) {
|
||||
return std::cosf(x);
|
||||
}
|
||||
|
||||
void KYTY_SYSV_ABI sincosf(float x, float* sinp, float* cosp) {
|
||||
if (sinp != nullptr) {
|
||||
*sinp = std::sinf(x);
|
||||
}
|
||||
if (cosp != nullptr) {
|
||||
*cosp = std::cosf(x);
|
||||
}
|
||||
}
|
||||
|
||||
double KYTY_SYSV_ABI sin(double x) {
|
||||
return std::sin(x);
|
||||
}
|
||||
|
||||
double KYTY_SYSV_ABI cos(double x) {
|
||||
return std::cos(x);
|
||||
}
|
||||
|
||||
void KYTY_SYSV_ABI sincos(double x, double* sinp, double* cosp) {
|
||||
if (sinp != nullptr) {
|
||||
*sinp = std::sin(x);
|
||||
}
|
||||
if (cosp != nullptr) {
|
||||
*cosp = std::cos(x);
|
||||
}
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI LibcHeapErrorReportForGame(uint64_t msp, uint64_t ptr, uint64_t error,
|
||||
uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t temporary: heap error report ignored, msp=0x%016" PRIx64 ", ptr=0x%016" PRIx64
|
||||
", error=0x%016" PRIx64 ", args=(0x%016" PRIx64 ",0x%016" PRIx64 ",0x%016" PRIx64 ")\n",
|
||||
msp, ptr, error, arg3, arg4, arg5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitLibcInternal_1) {
|
||||
LibcInternalExt::InitLibcInternalExt_1(s);
|
||||
|
||||
LIB_OBJECT("ZT4ODD2Ts9o", &LibcInternal::g_need_flag);
|
||||
LIB_OBJECT("2sWzhYqFH4E", stdout);
|
||||
|
||||
LIB_FUNC("GMpvxPFW924", LibcInternal::vprintf);
|
||||
LIB_FUNC("MUjC4lbHrK4", LibcInternal::fflush);
|
||||
LIB_FUNC("8zTFvBIAIN8", LibcInternal::memset);
|
||||
LIB_FUNC("Q3VBxCXhUHs", LibcInternal::memcpy);
|
||||
LIB_FUNC("+P6FRGH4LfA", LibcInternal::memmove);
|
||||
LIB_FUNC("DfivPArhucg", LibcInternal::memcmp);
|
||||
LIB_FUNC("aesyjrHVWy4", LibcInternal::strcmp);
|
||||
LIB_FUNC("Ovb2dSJOAuE", LibcInternal::strncmp);
|
||||
LIB_FUNC("j4ViWNHEgww", LibcInternal::strlen);
|
||||
LIB_FUNC("5Xa2ACNECdo", LibcInternal::strcpy);
|
||||
LIB_FUNC("6sJWiWSRuqk", LibcInternal::strncpy);
|
||||
LIB_FUNC("Ls4tzzhimqQ", LibcInternal::strcat);
|
||||
LIB_FUNC("ob5xAW4ln-0", LibcInternal::strchr);
|
||||
LIB_FUNC("9yDWMxEFdJU", LibcInternal::strrchr);
|
||||
LIB_FUNC("viiwFMaNamA", LibcInternal::strstr);
|
||||
LIB_FUNC("mXlxhmLNMPg", LibcInternal::strtol);
|
||||
LIB_FUNC("QxmSHBCuKTk", LibcInternal::strtoul);
|
||||
LIB_FUNC("zlfEH8FmyUA", LibcInternal::strtoul);
|
||||
LIB_FUNC("fPxypibz2MY", LibcInternal::atoi);
|
||||
LIB_FUNC("Q4rRL34CEeE", LibcInternal::sinf);
|
||||
LIB_FUNC("-P6FNMzk2Kc", LibcInternal::cosf);
|
||||
LIB_FUNC("pztV4AF18iI", LibcInternal::sincosf);
|
||||
LIB_FUNC("H8ya2H00jbI", LibcInternal::sin);
|
||||
LIB_FUNC("2WE3BTYVwKM", LibcInternal::cos);
|
||||
LIB_FUNC("jMB7EFyu30Y", LibcInternal::sincos);
|
||||
LIB_FUNC("eLdDw6l0-bU", LibcInternal::snprintf);
|
||||
|
||||
LIB_FUNC("L1SBTkC+Cvw", LibC::abort);
|
||||
LIB_FUNC("tsvEmnenz48", LibC::cxa_atexit);
|
||||
LIB_FUNC("H2e8t5ScQGc", LibC::cxa_finalize);
|
||||
LIB_FUNC("DiGVep5yB5w", LibC::std_execute_once);
|
||||
|
||||
LIB_FUNC("al3JzFI9MQ0", LibcInternal::LibcHeapErrorReportForGame);
|
||||
}
|
||||
|
||||
} // namespace LibcInternal
|
||||
|
||||
LIB_USING(LibC);
|
||||
|
||||
LIB_DEFINE(InitLibC_1) {
|
||||
LibcInternal::InitLibcInternal_1(s);
|
||||
|
||||
LIB_OBJECT("P330P3dFF68", &LibC::g_need_flag);
|
||||
|
||||
LIB_FUNC("uMei1W9uyNo", LibC::exit);
|
||||
LIB_FUNC("L1SBTkC+Cvw", LibC::abort);
|
||||
LIB_FUNC("9BcDykPmo1I", LibC::libc_error);
|
||||
LIB_FUNC("bzQExy189ZI", LibC::init_env);
|
||||
LIB_FUNC("8G2LB+A3rzg", LibC::atexit);
|
||||
LIB_FUNC("hcuQgD53UxM", LibC::libc_printf);
|
||||
LIB_FUNC("YQ0navp+YIc", LibC::puts);
|
||||
LIB_FUNC("M4YYbSFfJ8g", LibC::setenv);
|
||||
LIB_FUNC("wLlFkwG9UcQ", LibC::libc_time);
|
||||
LIB_FUNC("-VVn74ZyhEs", LibC::libc_difftime);
|
||||
LIB_FUNC("1mecP7RgI2A", LibC::libc_gmtime);
|
||||
LIB_FUNC("efhK-YSUYYQ", LibC::libc_localtime);
|
||||
LIB_FUNC("n7AepwR0s34", LibC::libc_mktime);
|
||||
LIB_FUNC("Av3zjWi64Kw", LibC::libc_strftime);
|
||||
LIB_FUNC("XKRegsFpEpk", LibC::catchReturnFromMain);
|
||||
LIB_FUNC("tsvEmnenz48", LibC::cxa_atexit);
|
||||
LIB_FUNC("H2e8t5ScQGc", LibC::cxa_finalize);
|
||||
LIB_FUNC("DiGVep5yB5w", LibC::std_execute_once);
|
||||
LIB_FUNC("YaHc3GS7y7g", LibC::MtxInit);
|
||||
LIB_FUNC("tgioGpKtmbE", LibC::MtxInitWithName);
|
||||
LIB_FUNC("JHp7ogc1+HY", LibC::MtxInitWithDefaultNameOverride);
|
||||
LIB_FUNC("5Lf51jvohTQ", LibC::MtxDestroy);
|
||||
LIB_FUNC("iS4aWbUonl0", LibC::MtxLock);
|
||||
LIB_FUNC("k6pGNMwJB08", LibC::MtxTrylock);
|
||||
LIB_FUNC("hPzYSd5Nasc", LibC::MtxTimedlock);
|
||||
LIB_FUNC("gTuXQwP9rrs", LibC::MtxUnlock);
|
||||
LIB_FUNC("VYQwFs4CC4Y", LibC::MtxCurrentOwns);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,235 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/platform/sysDbg.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/threads.h"
|
||||
#include "common/virtualMemory.h"
|
||||
#include "kernel/memory.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("DbgAddressSanitizer", 1, "DbgAddressSanitizer", 1, 1);
|
||||
|
||||
namespace DbgAddressSanitizer {
|
||||
|
||||
struct SourceLocation {
|
||||
const char* filename;
|
||||
int line_no;
|
||||
int column_no;
|
||||
};
|
||||
|
||||
struct Global {
|
||||
uintptr_t beg;
|
||||
uintptr_t size;
|
||||
uintptr_t size_with_redzone;
|
||||
const char* name;
|
||||
const char* module_name;
|
||||
uintptr_t has_dynamic_init;
|
||||
SourceLocation* location;
|
||||
uintptr_t odr_indicator;
|
||||
};
|
||||
|
||||
struct Shadow {
|
||||
uintptr_t start = 0;
|
||||
int count = 0;
|
||||
};
|
||||
|
||||
struct AsanContext {
|
||||
Common::Mutex mutex;
|
||||
std::vector<Shadow> shadows;
|
||||
};
|
||||
|
||||
static uint32_t g_fake_stack = 0;
|
||||
static AsanContext* g_ctx = nullptr;
|
||||
|
||||
static void AllocShadow(uintptr_t min_addr, uintptr_t max_addr) {
|
||||
EXIT_IF(g_ctx == nullptr);
|
||||
|
||||
Common::LockGuard lock(g_ctx->mutex);
|
||||
|
||||
static const uintptr_t page_size = 0x10000ull;
|
||||
|
||||
auto min_shadow = ((min_addr >> 3u) + 0x10000000000ull) & ~(page_size - 1);
|
||||
auto max_shadow = ((max_addr >> 3u) + 0x10000000000ull) & ~(page_size - 1);
|
||||
|
||||
auto size = max_shadow - min_shadow + page_size;
|
||||
|
||||
LOGF("\t shadow = %016" PRIx64 "\n"
|
||||
"\t size = %016" PRIx64 "\n",
|
||||
static_cast<uint64_t>(min_shadow), static_cast<uint64_t>(size));
|
||||
|
||||
for (uintptr_t page = min_shadow; page <= max_shadow; page += page_size) {
|
||||
const auto it = std::find_if(g_ctx->shadows.begin(), g_ctx->shadows.end(),
|
||||
[page](const Shadow& s) { return s.start == page; });
|
||||
if (it != g_ctx->shadows.end()) {
|
||||
it->count++;
|
||||
} else {
|
||||
if (!Common::VirtualMemory::AllocFixed(page, page_size,
|
||||
Common::VirtualMemory::Mode::ReadWrite)) {
|
||||
EXIT("can't allocate shadow memory\n");
|
||||
}
|
||||
|
||||
Shadow s;
|
||||
s.start = page;
|
||||
s.count = 1;
|
||||
g_ctx->shadows.push_back(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FreeShadow(uintptr_t min_addr, uintptr_t max_addr) {
|
||||
EXIT_IF(g_ctx == nullptr);
|
||||
|
||||
Common::LockGuard lock(g_ctx->mutex);
|
||||
|
||||
static const uintptr_t page_size = 0x10000ull;
|
||||
|
||||
auto min_shadow = ((min_addr >> 3u) + 0x10000000000ull) & ~(page_size - 1);
|
||||
auto max_shadow = ((max_addr >> 3u) + 0x10000000000ull) & ~(page_size - 1);
|
||||
|
||||
auto size = max_shadow - min_shadow + page_size;
|
||||
|
||||
LOGF("\t shadow = %016" PRIx64 "\n"
|
||||
"\t size = %016" PRIx64 "\n",
|
||||
static_cast<uint64_t>(min_shadow), static_cast<uint64_t>(size));
|
||||
|
||||
for (uintptr_t page = min_shadow; page <= max_shadow; page += page_size) {
|
||||
const auto it = std::find_if(g_ctx->shadows.begin(), g_ctx->shadows.end(),
|
||||
[page](const Shadow& s) { return s.start == page; });
|
||||
if (it != g_ctx->shadows.end()) {
|
||||
it->count--;
|
||||
|
||||
if (it->count <= 0) {
|
||||
if (!Common::VirtualMemory::Free(page)) {
|
||||
EXIT("can't free shadow memory\n");
|
||||
}
|
||||
|
||||
g_ctx->shadows.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void KernelAlloc(uintptr_t addr, size_t size) {
|
||||
AllocShadow(addr, addr + size - 1);
|
||||
}
|
||||
|
||||
static void KernelFree(uintptr_t addr, size_t size) {
|
||||
FreeShadow(addr, addr + size - 1);
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI asan_init() {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(g_ctx != nullptr);
|
||||
|
||||
g_ctx = new AsanContext;
|
||||
|
||||
sys_dbg_stack_info_t s {};
|
||||
SysStackUsage(s);
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
||||
AllocShadow(s.addr, reinterpret_cast<uintptr_t>(&s));
|
||||
#else
|
||||
AllocShadow(s.reserved_addr, reinterpret_cast<uintptr_t>(&s));
|
||||
#endif
|
||||
|
||||
LibKernel::Memory::RegisterCallbacks(KernelAlloc, KernelFree);
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI asan_version_mismatch_check_v8() {
|
||||
PRINT_NAME();
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI asan_register_elf_globals(uintptr_t* flag, Global* start, Global* stop) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t flag = %016" PRIx64 "\n"
|
||||
"\t start = %016" PRIx64 "\n"
|
||||
"\t stop = %016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(flag), reinterpret_cast<uint64_t>(start),
|
||||
reinterpret_cast<uint64_t>(stop));
|
||||
|
||||
if (flag == nullptr || start == nullptr || stop == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (*flag != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto num = stop - start;
|
||||
|
||||
if (num != 0) {
|
||||
uintptr_t min_addr = UINTPTR_MAX;
|
||||
uintptr_t max_addr = 0;
|
||||
|
||||
for (ptrdiff_t i = 0; i < num; i++) {
|
||||
auto* g = start + i;
|
||||
|
||||
LOGF("asan global:\n"
|
||||
"\t beg = %016" PRIx64 "\n"
|
||||
"\t size = %016" PRIx64 "\n"
|
||||
"\t size_with_redzone = %016" PRIx64 "\n"
|
||||
"\t name = %s\n"
|
||||
"\t module_name = %s\n"
|
||||
"\t has_dynamic_init = %" PRIu64 "\n"
|
||||
"\t odr_indicator = %016" PRIx64 "\n",
|
||||
static_cast<uint64_t>(g->beg), static_cast<uint64_t>(g->size),
|
||||
static_cast<uint64_t>(g->size_with_redzone), g->name, g->module_name,
|
||||
static_cast<uint64_t>(g->has_dynamic_init),
|
||||
static_cast<uint64_t>(g->odr_indicator));
|
||||
if (g->location != nullptr) {
|
||||
LOGF("\t location = %s:%d\n", g->location->filename, g->location->line_no);
|
||||
}
|
||||
|
||||
min_addr = std::min(g->beg, min_addr);
|
||||
max_addr = std::max(g->beg + g->size_with_redzone - 1, max_addr);
|
||||
}
|
||||
|
||||
AllocShadow(min_addr, max_addr);
|
||||
}
|
||||
|
||||
*flag = 0;
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI asan_before_dynamic_init(const char* module_name) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t name = %s\n", module_name);
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI asan_after_dynamic_init() {
|
||||
PRINT_NAME();
|
||||
}
|
||||
|
||||
static void* KYTY_SYSV_ABI asan_memcpy(void* dst, const void* src, size_t size) {
|
||||
return std::memcpy(dst, src, size);
|
||||
}
|
||||
|
||||
static void* KYTY_SYSV_ABI asan_memset(void* dst, int ch, size_t size) {
|
||||
return std::memset(dst, ch, size);
|
||||
}
|
||||
|
||||
} // namespace DbgAddressSanitizer
|
||||
|
||||
LIB_DEFINE(InitDbgAddressSanitizer_1) {
|
||||
LIB_OBJECT("OmecxEgrhCs", &DbgAddressSanitizer::g_fake_stack);
|
||||
|
||||
LIB_FUNC("xLoVJKHvRMU", DbgAddressSanitizer::asan_init);
|
||||
LIB_FUNC("GY2I-Okc7q0", DbgAddressSanitizer::asan_version_mismatch_check_v8);
|
||||
LIB_FUNC("W+2HQAGdPuU", DbgAddressSanitizer::asan_register_elf_globals);
|
||||
LIB_FUNC("G9xSYlaNv+Y", DbgAddressSanitizer::asan_before_dynamic_init);
|
||||
LIB_FUNC("z5Gy5T3tptE", DbgAddressSanitizer::asan_after_dynamic_init);
|
||||
LIB_FUNC("g+Neom2EHO8", DbgAddressSanitizer::asan_memcpy);
|
||||
LIB_FUNC("q-hZf47nHhQ", DbgAddressSanitizer::asan_memset);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibRazorCpu {
|
||||
|
||||
LIB_VERSION("RazorCpu", 1, "RazorCpu", 1, 1);
|
||||
|
||||
static KYTY_SYSV_ABI uint32_t RazorCpuIsCapturing() {
|
||||
PRINT_NAME();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitLibRazorCpu_1) {
|
||||
LIB_FUNC("EboejOQvLL4", LibRazorCpu::RazorCpuIsCapturing);
|
||||
}
|
||||
|
||||
} // namespace LibRazorCpu
|
||||
|
||||
LIB_DEFINE(InitDebug_1) {
|
||||
LibRazorCpu::InitLibRazorCpu_1(s);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,136 @@
|
||||
#include "common/abi.h"
|
||||
#include "libs/dialog.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibCommonDialog {
|
||||
|
||||
LIB_VERSION("CommonDialog", 1, "CommonDialog", 1, 1);
|
||||
|
||||
namespace CommonDialog = Dialog::CommonDialog;
|
||||
|
||||
LIB_DEFINE(InitDialog_1_CommonDialog) {
|
||||
LIB_FUNC("uoUpLGNkygk", CommonDialog::CommonDialogInitialize);
|
||||
}
|
||||
|
||||
} // namespace LibCommonDialog
|
||||
|
||||
namespace LibImeDialog {
|
||||
|
||||
LIB_VERSION("ImeDialog", 1, "ImeDialog", 1, 1);
|
||||
|
||||
namespace ImeDialog = Dialog::ImeDialog;
|
||||
|
||||
LIB_DEFINE(InitDialog_1_ImeDialog) {
|
||||
LIB_FUNC("IADmD4tScBY", ImeDialog::ImeDialogGetStatus);
|
||||
}
|
||||
|
||||
} // namespace LibImeDialog
|
||||
|
||||
namespace LibLoginDialog {
|
||||
|
||||
LIB_VERSION("LoginDialog", 1, "LoginDialog", 1, 1);
|
||||
|
||||
namespace LoginDialog = Dialog::LoginDialog;
|
||||
|
||||
LIB_DEFINE(InitDialog_1_LoginDialog) {
|
||||
LIB_FUNC("qP-EvQRl2Hc", LoginDialog::LoginDialogInitialize);
|
||||
LIB_FUNC("vMQJRUKsf3U", LoginDialog::LoginDialogTerminate);
|
||||
LIB_FUNC("S56ra1+Tymg", LoginDialog::LoginDialogOpen);
|
||||
LIB_FUNC("F0XIzrG5yvw", LoginDialog::LoginDialogClose);
|
||||
LIB_FUNC("2rc+egSfb5A", LoginDialog::LoginDialogUpdateStatus);
|
||||
LIB_FUNC("HAiWUEwEfGo", LoginDialog::LoginDialogGetStatus);
|
||||
LIB_FUNC("Btkx21f1M8k", LoginDialog::LoginDialogGetResult);
|
||||
LIB_FUNC("3NPobi5lNmk", LoginDialog::LoginDialogParamInitialize);
|
||||
}
|
||||
|
||||
} // namespace LibLoginDialog
|
||||
|
||||
namespace LibSaveDataDialog {
|
||||
|
||||
LIB_VERSION("SaveDataDialog", 1, "SaveDataDialog", 1, 1);
|
||||
|
||||
namespace SaveDataDialog = Dialog::SaveDataDialog;
|
||||
|
||||
LIB_DEFINE(InitDialog_1_SaveDataDialog) {
|
||||
LIB_FUNC("ERKzksauAJA", SaveDataDialog::SaveDataDialogGetStatus);
|
||||
LIB_FUNC("KK3Bdg1RWK0", SaveDataDialog::SaveDataDialogUpdateStatus);
|
||||
LIB_FUNC("YuH2FA7azqQ", SaveDataDialog::SaveDataDialogTerminate);
|
||||
LIB_FUNC("V-uEeFKARJU", SaveDataDialog::SaveDataDialogProgressBarInc);
|
||||
LIB_FUNC("hay1CfTmLyA", SaveDataDialog::SaveDataDialogProgressBarSetValue);
|
||||
}
|
||||
|
||||
} // namespace LibSaveDataDialog
|
||||
|
||||
namespace LibSaveDataDialogNative {
|
||||
|
||||
LIB_VERSION("SaveDataDialog.native", 1, "SaveDataDialog", 1, 1);
|
||||
|
||||
namespace SaveDataDialog = Dialog::SaveDataDialog;
|
||||
|
||||
LIB_DEFINE(InitDialog_1_SaveDataDialogNative) {
|
||||
LIB_FUNC("fH46Lag88XY", SaveDataDialog::SaveDataDialogClose);
|
||||
LIB_FUNC("yEiJ-qqr6Cg", SaveDataDialog::SaveDataDialogGetResult);
|
||||
LIB_FUNC("ERKzksauAJA", SaveDataDialog::SaveDataDialogGetStatus);
|
||||
LIB_FUNC("s9e3+YpRnzw", SaveDataDialog::SaveDataDialogInitialize);
|
||||
LIB_FUNC("en7gNVnh878", SaveDataDialog::SaveDataDialogIsReadyToDisplay);
|
||||
LIB_FUNC("4tPhsP6FpDI", SaveDataDialog::SaveDataDialogOpen);
|
||||
LIB_FUNC("V-uEeFKARJU", SaveDataDialog::SaveDataDialogProgressBarInc);
|
||||
LIB_FUNC("hay1CfTmLyA", SaveDataDialog::SaveDataDialogProgressBarSetValue);
|
||||
LIB_FUNC("YuH2FA7azqQ", SaveDataDialog::SaveDataDialogTerminate);
|
||||
LIB_FUNC("KK3Bdg1RWK0", SaveDataDialog::SaveDataDialogUpdateStatus);
|
||||
}
|
||||
|
||||
} // namespace LibSaveDataDialogNative
|
||||
|
||||
namespace LibMsgDialog {
|
||||
|
||||
LIB_VERSION("MsgDialog.native", 1, "MsgDialog", 1, 1);
|
||||
|
||||
namespace MsgDialog = Dialog::MsgDialog;
|
||||
|
||||
LIB_DEFINE(InitDialog_1_MsgDialog) {
|
||||
LIB_FUNC("HTrcDKlFKuM", MsgDialog::MsgDialogClose);
|
||||
LIB_FUNC("Lr8ovHH9l6A", MsgDialog::MsgDialogGetResult);
|
||||
LIB_FUNC("CWVW78Qc3fI", MsgDialog::MsgDialogGetStatus);
|
||||
LIB_FUNC("lDqxaY1UbEo", MsgDialog::MsgDialogInitialize);
|
||||
LIB_FUNC("b06Hh0DPEaE", MsgDialog::MsgDialogOpen);
|
||||
LIB_FUNC("Gc5k1qcK4fs", MsgDialog::MsgDialogProgressBarInc);
|
||||
LIB_FUNC("6H-71OdrpXM", MsgDialog::MsgDialogProgressBarSetMsg);
|
||||
LIB_FUNC("wTpfglkmv34", MsgDialog::MsgDialogProgressBarSetValue);
|
||||
LIB_FUNC("ePw-kqZmelo", MsgDialog::MsgDialogTerminate);
|
||||
LIB_FUNC("6fIC3XKt2k0", MsgDialog::MsgDialogUpdateStatus);
|
||||
}
|
||||
|
||||
} // namespace LibMsgDialog
|
||||
|
||||
namespace LibErrorDialog {
|
||||
|
||||
LIB_VERSION("ErrorDialog", 1, "ErrorDialog", 1, 1);
|
||||
|
||||
namespace ErrorDialog = Dialog::ErrorDialog;
|
||||
|
||||
LIB_DEFINE(InitDialog_1_ErrorDialog) {
|
||||
LIB_FUNC("ekXHb1kDBl0", ErrorDialog::ErrorDialogClose);
|
||||
LIB_FUNC("t2FvHRXzgqk", ErrorDialog::ErrorDialogGetStatus);
|
||||
LIB_FUNC("I88KChlynSs", ErrorDialog::ErrorDialogInitialize);
|
||||
LIB_FUNC("M2ZF-ClLhgY", ErrorDialog::ErrorDialogOpen);
|
||||
LIB_FUNC("9XAxK2PMwk8", ErrorDialog::ErrorDialogTerminate);
|
||||
LIB_FUNC("WWiGuh9XfgQ", ErrorDialog::ErrorDialogUpdateStatus);
|
||||
}
|
||||
|
||||
} // namespace LibErrorDialog
|
||||
|
||||
LIB_DEFINE(InitDialog_1) {
|
||||
LibCommonDialog::InitDialog_1_CommonDialog(s);
|
||||
LibImeDialog::InitDialog_1_ImeDialog(s);
|
||||
LibLoginDialog::InitDialog_1_LoginDialog(s);
|
||||
LibSaveDataDialog::InitDialog_1_SaveDataDialog(s);
|
||||
LibSaveDataDialogNative::InitDialog_1_SaveDataDialogNative(s);
|
||||
LibMsgDialog::InitDialog_1_MsgDialog(s);
|
||||
LibErrorDialog::InitDialog_1_ErrorDialog(s);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,45 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("FontFt", 1, "FontFt", 1, 1);
|
||||
|
||||
namespace FontFt {
|
||||
|
||||
struct SelectionState {
|
||||
int value;
|
||||
int kind;
|
||||
};
|
||||
|
||||
void* KYTY_SYSV_ABI FontSelectLibraryFt(int value) {
|
||||
PRINT_NAME();
|
||||
|
||||
static SelectionState s_selection {};
|
||||
s_selection.value = value;
|
||||
s_selection.kind = 0;
|
||||
|
||||
return &s_selection;
|
||||
}
|
||||
|
||||
void* KYTY_SYSV_ABI FontSelectRendererFt(int value) {
|
||||
PRINT_NAME();
|
||||
|
||||
static SelectionState s_selection {};
|
||||
s_selection.value = value;
|
||||
s_selection.kind = 1;
|
||||
|
||||
return &s_selection;
|
||||
}
|
||||
|
||||
} // namespace FontFt
|
||||
|
||||
LIB_DEFINE(InitFontFt_1) {
|
||||
LIB_FUNC("oM+XCzVG3oM", FontFt::FontSelectLibraryFt);
|
||||
LIB_FUNC("Xx974EW-QFY", FontFt::FontSelectRendererFt);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,324 @@
|
||||
#include "common/abi.h"
|
||||
#include "libs/agc.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibGen5 {
|
||||
|
||||
LIB_VERSION("Graphics5", 1, "Graphics5", 1, 1);
|
||||
|
||||
namespace Gen5 = Graphics::Gen5;
|
||||
|
||||
template <class T>
|
||||
static T ReadUnaligned(const uint8_t* ptr, uint32_t offset) {
|
||||
T ret {};
|
||||
std::memcpy(&ret, ptr + offset, sizeof(T));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t BitExtract(uint32_t value, uint32_t start, uint32_t len) {
|
||||
return (value >> start) & ((1u << len) - 1u);
|
||||
}
|
||||
|
||||
static void Graphics5UnknownDbWriteDefault(uint64_t* out, uint32_t first) {
|
||||
constexpr uint64_t default_entry = 0x10000000ull;
|
||||
|
||||
for (uint32_t i = first; i < 32u; i++) {
|
||||
const auto low = static_cast<uint32_t>(default_entry) + i;
|
||||
const auto high = static_cast<uint32_t>(default_entry >> 37u) * 32u + i;
|
||||
out[i] = (static_cast<uint64_t>(high) << 32u) | low;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t Graphics5UnknownDbApplyTwoBitField(uint32_t value, uint32_t field, uint32_t shift) {
|
||||
const auto mask = 0x3u << shift;
|
||||
|
||||
switch (field & 0x3u) {
|
||||
case 0: return value & ~mask;
|
||||
case 1: return (value & ~mask) | (0x1u << shift);
|
||||
case 2: return (value & ~mask) | (0x2u << shift);
|
||||
default: return value | mask;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t Graphics5UnknownDbApplyFinalMask(uint32_t flags, uint32_t src,
|
||||
uint32_t mask_value) {
|
||||
flags &= 0xffffffe0u;
|
||||
flags |= BitExtract(mask_value, 8u, 5u);
|
||||
flags &= 0xfffffbffu;
|
||||
flags |= ((src & 0x400000u) != 0 ? 0x400u : ((src >> 14u) & 0x400u));
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI Graphics5UnknownDb(uint64_t arg0, uint64_t arg1, uint64_t arg2,
|
||||
uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
||||
PRINT_NAME();
|
||||
|
||||
(void)arg3;
|
||||
(void)arg4;
|
||||
(void)arg5;
|
||||
|
||||
auto* out = reinterpret_cast<uint64_t*>(arg0);
|
||||
|
||||
if (arg2 == 0) {
|
||||
Graphics5UnknownDbWriteDefault(out, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto* desc = reinterpret_cast<const uint8_t*>(arg1);
|
||||
const auto* src = reinterpret_cast<const uint8_t*>(arg2);
|
||||
|
||||
const auto count = ReadUnaligned<uint32_t>(src, 0x50u);
|
||||
|
||||
if (count == 0) {
|
||||
Graphics5UnknownDbWriteDefault(out, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto mask_count = ReadUnaligned<uint16_t>(desc, 0x56u);
|
||||
const auto* masks = reinterpret_cast<const uint32_t*>(ReadUnaligned<uint64_t>(desc, 0x38u));
|
||||
const auto* src_entries =
|
||||
reinterpret_cast<const uint32_t*>(ReadUnaligned<uint64_t>(src, 0x30u));
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
auto src_value = src_entries[i];
|
||||
auto mask_index = static_cast<uint32_t>(mask_count);
|
||||
|
||||
for (uint32_t j = 0; j < mask_count; j++) {
|
||||
if ((static_cast<uint8_t>(masks[j]) ^ static_cast<uint8_t>(src_value)) == 0) {
|
||||
mask_index = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const bool has_mask = (mask_index < mask_count);
|
||||
const auto mode = (src_value >> 20u) & 0x3u;
|
||||
auto flags = 0u;
|
||||
|
||||
if (mode == 0) {
|
||||
flags = (((src_value >> 24u) & 0x1u) | (has_mask ? 0u : 1u)) << 5u;
|
||||
flags = Graphics5UnknownDbApplyTwoBitField(flags, (src_value >> 28u) & 0x3u, 8u);
|
||||
} else {
|
||||
const auto shifted_mode = (src_value << 4u) & 0x03000000u;
|
||||
flags = shifted_mode + 0x80000u;
|
||||
|
||||
if (mode == 2) {
|
||||
flags &= 0xffefffdfu;
|
||||
if (has_mask) {
|
||||
flags |= ((~(masks[mask_index] & src_value) >> 16u) & 0x20u);
|
||||
} else {
|
||||
flags |= 0x20u;
|
||||
}
|
||||
flags = Graphics5UnknownDbApplyTwoBitField(flags, (src_value >> 30u) & 0x3u, 8u);
|
||||
flags = Graphics5UnknownDbApplyTwoBitField(flags, (src_value >> 30u) & 0x3u, 21u);
|
||||
} else {
|
||||
if (has_mask) {
|
||||
const auto masked = masks[mask_index] & src_value;
|
||||
flags &= 0xffffffdfu;
|
||||
flags |= (masked >> 15u) & 0x20u;
|
||||
flags ^= 0x20u;
|
||||
flags &= 0xffefffffu;
|
||||
flags |= ((~masked >> 1u) & 0x100000u);
|
||||
flags =
|
||||
Graphics5UnknownDbApplyTwoBitField(flags, (src_value >> 30u) & 0x3u, 8u);
|
||||
} else {
|
||||
flags |= 0x100020u;
|
||||
flags =
|
||||
Graphics5UnknownDbApplyTwoBitField(flags, (src_value >> 28u) & 0x3u, 8u);
|
||||
}
|
||||
flags = Graphics5UnknownDbApplyTwoBitField(flags, (src_value >> 30u) & 0x3u, 21u);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_mask) {
|
||||
flags = Graphics5UnknownDbApplyFinalMask(flags, src_value, masks[mask_index]);
|
||||
} else {
|
||||
flags &= 0xfffffbe0u;
|
||||
}
|
||||
|
||||
out[i] = (static_cast<uint64_t>(flags) << 32u) | (0x10000000u + i);
|
||||
}
|
||||
|
||||
if (count < 32u) {
|
||||
Graphics5UnknownDbWriteDefault(out, count);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitGraphicsDriver_1) {
|
||||
PRINT_NAME_ENABLE(true);
|
||||
|
||||
LIB_FUNC("23LRUSvYu1M", Gen5::GraphicsInit);
|
||||
LIB_FUNC("2JtWUUiYBXs", Gen5::GraphicsGetRegisterDefaults2);
|
||||
LIB_FUNC("wRbq6ZjNop4", Gen5::GraphicsGetRegisterDefaults2Internal);
|
||||
LIB_FUNC("f3dg2CSgRKY", Gen5::GraphicsCreateShader);
|
||||
LIB_FUNC("dolOmWH+huQ", Gen5::GraphicsUnknownGetFusedShaderSize);
|
||||
LIB_FUNC("fd5Bp5tGTgo", Gen5::GraphicsUnknownFuseShaderHalves);
|
||||
LIB_FUNC("vcmNN+AAXnY", Gen5::GraphicsSetCxRegIndirectPatchSetAddress);
|
||||
LIB_FUNC("Qrj4c+61z4A", Gen5::GraphicsSetShRegIndirectPatchSetAddress);
|
||||
LIB_FUNC("6lNcCp+fxi4", Gen5::GraphicsSetUcRegIndirectPatchSetAddress);
|
||||
LIB_FUNC("whb1RL7K4Ss", Gen5::GraphicsSetCxRegIndirectPatchSetNumRegisters);
|
||||
LIB_FUNC("nCUgItdN2ms", Gen5::GraphicsSetShRegIndirectPatchSetNumRegisters);
|
||||
LIB_FUNC("fRG-JOH5+sI", Gen5::GraphicsSetUcRegIndirectPatchSetNumRegisters);
|
||||
LIB_FUNC("d-6uF9sZDIU", Gen5::GraphicsSetCxRegIndirectPatchAddRegisters);
|
||||
LIB_FUNC("z2duB-hHQSM", Gen5::GraphicsSetShRegIndirectPatchAddRegisters);
|
||||
LIB_FUNC("vRoArM9zaIk", Gen5::GraphicsSetUcRegIndirectPatchAddRegisters);
|
||||
LIB_FUNC("D9sr1xGUriE", Gen5::GraphicsCreatePrimState);
|
||||
LIB_FUNC("Y3ymLfZ1384", Gen5::GraphicsUpdatePrimState);
|
||||
LIB_FUNC("HV4j+E0MBHE", Gen5::GraphicsCreateInterpolantMapping);
|
||||
LIB_FUNC("V++UgBtQhn0", Gen5::GraphicsGetDataPacketPayloadAddress);
|
||||
LIB_FUNC("s+VGAMDQ0AQ", Gen5::GraphicsGetDataPacketPayloadRange);
|
||||
LIB_FUNC("fPSCdQxgpSw", Gen5::GraphicsWriteDataPatchSetAddressOrOffset);
|
||||
LIB_FUNC("bxca0BK4FNg", Gen5::GraphicsUnknownJumpPatchSetTarget);
|
||||
LIB_FUNC("2BS4EtAaF28", Gen5::GraphicsJumpPatchSetTarget);
|
||||
LIB_FUNC("h9z6+0hEydk", Gen5::GraphicsSuspendPoint);
|
||||
LIB_FUNC("qj7QZpgr9Uw", Gen5::GraphicsUnknownQj7QZpgr9Uw);
|
||||
LIB_FUNC("BfBDZGbti7A", Gen5::GraphicsGetIsTrinityMode);
|
||||
LIB_FUNC("dbOlWdppb4o", LibGen5::Graphics5UnknownDb);
|
||||
|
||||
LIB_FUNC("F0ZXt5q0ZTA", Gen5::GraphicsDriverGetDefaultOwner);
|
||||
LIB_FUNC("F0Y42t-3e18", Gen5::GraphicsDriverInitResourceRegistration);
|
||||
LIB_FUNC("AOLcoIkQDgM", Gen5::GraphicsDriverQueryResourceRegistrationUserMemoryRequirements);
|
||||
LIB_FUNC("uJziRsODk1c", Gen5::GraphicsDriverGetResourceRegistrationMaxNameLength);
|
||||
LIB_FUNC("X-Nm5KLREeg", Gen5::GraphicsDriverRegisterOwner);
|
||||
LIB_FUNC("W5z4eZrjEas", Gen5::GraphicsDriverRegisterResource);
|
||||
LIB_FUNC("pWLG7WOpVcw", Gen5::GraphicsDriverUnregisterResource);
|
||||
LIB_FUNC("3AyTaWcF-H8", Gen5::GraphicsDriverRegisterWorkloadStream);
|
||||
|
||||
LIB_FUNC("LtTouSCZjHM", Gen5::GraphicsCbNop);
|
||||
LIB_FUNC("t7PlZ9nt5Lc", Gen5::GraphicsCbNopGetSize);
|
||||
LIB_FUNC("k3GhuSNmBLU", Gen5::GraphicsCbDispatch);
|
||||
LIB_FUNC("Abendgtz+3o", Gen5::GraphicsCbDispatchGetSize);
|
||||
LIB_FUNC("w1KFAHVqpaU", Gen5::GraphicsCbBranch);
|
||||
LIB_FUNC("n2fD4A+pb+g", Gen5::GraphicsCbSetShRegisterRangeDirect);
|
||||
LIB_FUNC("bxGoVxpdSPQ", Gen5::GraphicsCbSetShRegisterRangeDirectGetSize);
|
||||
LIB_FUNC("UZbQjYAwwXM", Gen5::GraphicsCbSetShRegistersDirect);
|
||||
LIB_FUNC("wr23dPKyWc0", Gen5::GraphicsCbReleaseMem);
|
||||
LIB_FUNC("hL7C0IRpWZI", Gen5::GraphicsCbQueueEndOfPipeActionGetSize);
|
||||
LIB_FUNC("T6xuVw0KUJo", Gen5::GraphicsDebugRaiseException);
|
||||
LIB_FUNC("JrtiDtKeS38", Gen5::GraphicsAcbResetQueue);
|
||||
LIB_FUNC("cFazmnXpJOE", Gen5::GraphicsAcbEventWrite);
|
||||
LIB_FUNC("KT-hTp-Ch14", Gen5::GraphicsAcbAcquireMem);
|
||||
LIB_FUNC("ewobAQeMo5k", Gen5::GraphicsAcbAcquireMemGetSize);
|
||||
LIB_FUNC("qyM2bxYFPAk", Gen5::GraphicsAcbCondExec);
|
||||
LIB_FUNC("ozKzBP4aki4", Gen5::GraphicsAcbCondExecGetSize);
|
||||
LIB_FUNC("htn36gPnBk4", Gen5::GraphicsAcbWaitRegMem);
|
||||
LIB_FUNC("-RnpfpxIhec", Gen5::GraphicsAcbDmaData);
|
||||
LIB_FUNC("qzMN2XKGA4k", Gen5::GraphicsAcbCopyData);
|
||||
LIB_FUNC("j3EtxFkSIhQ", Gen5::GraphicsAcbDispatchIndirect);
|
||||
LIB_FUNC("eZ4+17OQz4Q", Gen5::GraphicsAcbWriteData);
|
||||
LIB_FUNC("xAeBOa0A3kk", Gen5::GraphicsAcbSetMarker);
|
||||
LIB_FUNC("cpCILPya5Zk", Gen5::GraphicsAcbPushMarker);
|
||||
LIB_FUNC("6mFxkVqdmbQ", Gen5::GraphicsAcbPopMarker);
|
||||
LIB_FUNC("TRO721eVt4g", Gen5::GraphicsDcbResetQueue);
|
||||
LIB_FUNC("MWiElSNE8j8", Gen5::GraphicsDcbWaitUntilSafeForRendering);
|
||||
LIB_FUNC("LFSPFmGc9Hg", Gen5::GraphicsDcbSetWorkloadsActive);
|
||||
LIB_FUNC("hEK26Wdny6s", Gen5::GraphicsDcbSetWorkloadComplete);
|
||||
LIB_FUNC("QhCbS4X9Rl8", Gen5::GraphicsDcbSetMarker);
|
||||
LIB_FUNC("pFLArOT53+w", Gen5::GraphicsDcbSetShRegisterDirect);
|
||||
LIB_FUNC("LHFXRrlTPD8", Gen5::GraphicsDcbSetCxRegisterDirect);
|
||||
LIB_FUNC("1DeUNpRIDDA", Gen5::GraphicsDcbSetCxRegisterDirectGetSize);
|
||||
LIB_FUNC("w4-d0n60hdo", Gen5::GraphicsDcbSetUcRegisterDirect);
|
||||
LIB_FUNC("ZvwO9euwYzc", Gen5::GraphicsDcbSetCxRegistersIndirect);
|
||||
LIB_FUNC("-HOOCn0JY48", Gen5::GraphicsDcbSetShRegistersIndirect);
|
||||
LIB_FUNC("hvUfkUIQcOE", Gen5::GraphicsDcbSetUcRegistersIndirect);
|
||||
LIB_FUNC("GIIW2J37e70", Gen5::GraphicsDcbSetIndexSize);
|
||||
LIB_FUNC("l4fM9K-Lyks", Gen5::GraphicsDcbSetIndexBuffer);
|
||||
LIB_FUNC("8N2tmT3jmC8", Gen5::GraphicsDcbSetIndexCount);
|
||||
LIB_FUNC("tSBxhAPyytQ", Gen5::GraphicsDcbSetNumInstances);
|
||||
LIB_FUNC("6DFuRKT4C9w", Gen5::GraphicsDcbSetNumInstancesGetSize);
|
||||
LIB_FUNC("q88lQ+GP5Yk", Gen5::GraphicsDcbDrawIndex);
|
||||
LIB_FUNC("6ee9Hd3EWXQ", Gen5::GraphicsDcbDrawIndexGetSize);
|
||||
LIB_FUNC("Ikfdt-rIqCE", Gen5::GraphicsUnknownIkfdtRIqCE);
|
||||
LIB_FUNC("Rlx+bykm0r0", Gen5::GraphicsDcbDrawIndexMultiInstanced);
|
||||
LIB_FUNC("mR9j7+SfM34", Gen5::GraphicsDcbDrawIndexMultiInstancedGetSize);
|
||||
LIB_FUNC("Yw0jKSqop+E", Gen5::GraphicsDcbDrawIndexAuto);
|
||||
LIB_FUNC("WrdP9Zxx3lQ", Gen5::GraphicsDcbDrawIndexAutoGetSize);
|
||||
LIB_FUNC("B+aG9DUnTKA", Gen5::GraphicsDcbDrawIndexOffset);
|
||||
LIB_FUNC("qMlfB1ZhMDc", Gen5::GraphicsDcbDrawIndexOffsetGetSize);
|
||||
LIB_FUNC("RmaJwLtc8rY", Gen5::GraphicsDcbSetBaseIndirectArgs);
|
||||
LIB_FUNC("1q1titRBL6o", Gen5::GraphicsDcbDrawIndirect);
|
||||
LIB_FUNC("cxPZ4Wgvdj8", Gen5::GraphicsDcbDrawIndirectGetSize);
|
||||
LIB_FUNC("t1vNu082-jM", Gen5::GraphicsDcbDrawIndexIndirect);
|
||||
LIB_FUNC("ypVBz4uPKcQ", Gen5::GraphicsDcbDrawIndexIndirectMulti);
|
||||
LIB_FUNC("CtB+A9-VxO0", Gen5::GraphicsDcbDispatchIndirect);
|
||||
LIB_FUNC("w8HVkEeXPv8", Gen5::GraphicsDcbDispatchIndirectGetSize);
|
||||
LIB_FUNC("aJf+j5yntiU", Gen5::GraphicsDcbEventWrite);
|
||||
LIB_FUNC("57labkp+rSQ", Gen5::GraphicsDcbAcquireMem);
|
||||
LIB_FUNC("-vnlTPPXPrw", Gen5::GraphicsDcbAcquireMemGetSize);
|
||||
LIB_FUNC("1rZSWUv1IRc", Gen5::GraphicsDcbCopyData);
|
||||
LIB_FUNC("WmAc2MEj6Io", Gen5::GraphicsDcbDmaData);
|
||||
LIB_FUNC("xSAR0LTcRKM", Gen5::GraphicsDcbJump);
|
||||
LIB_FUNC("VEGu4dixjUg", Gen5::GraphicsDcbJumpGetSize);
|
||||
LIB_FUNC("QIXCsbipds0", Gen5::GraphicsDcbRewindGetSize);
|
||||
LIB_FUNC("zfcxg-ewMK8", Gen5::GraphicsDcbRewind);
|
||||
LIB_FUNC("BIPexNBSGog", Gen5::GraphicsDcbCondExec);
|
||||
LIB_FUNC("ou16V5hh5sg", Gen5::GraphicsDcbCondExecGetSize);
|
||||
LIB_FUNC("bbFueFP+J4k", Gen5::GraphicsDcbSetPredication);
|
||||
LIB_FUNC("-KRzWekV120", Gen5::GraphicsUnknownKRzWekV120);
|
||||
LIB_FUNC("IxYiarKlXxM", Gen5::GraphicsDmaDataPatchSetDstAddressOrOffset);
|
||||
LIB_FUNC("cdDRpqcFGbU", Gen5::GraphicsDmaDataPatchSetSrcAddressOrOffsetOrImmediate);
|
||||
LIB_FUNC("Lkf86B98qPc", Gen5::GraphicsGetPacketSize);
|
||||
LIB_FUNC("w6Dj1VJt5qY", Gen5::GraphicsSetPacketPredication);
|
||||
LIB_FUNC("n8vgpaQg6dA", Gen5::GraphicsSetRangePredication);
|
||||
LIB_FUNC("i1jyy49AjXU", Gen5::GraphicsDcbWriteData);
|
||||
LIB_FUNC("p9tI+yTvx68", Gen5::GraphicsDcbWriteDataGetSize);
|
||||
LIB_FUNC("vuSXe69VILM", Gen5::GraphicsDcbGetLodStats);
|
||||
LIB_FUNC("VmW0Tdpy420", Gen5::GraphicsDcbWaitRegMem);
|
||||
LIB_FUNC("43WJ08sSugE", Gen5::GraphicsDcbWaitOnAddressGetSize);
|
||||
LIB_FUNC("+kSrjIVxKFE", Gen5::GraphicsDcbPushMarker);
|
||||
LIB_FUNC("H7uZqCoNuWk", Gen5::GraphicsDcbPopMarker);
|
||||
LIB_FUNC("u2T2DiA5hRI", Gen5::GraphicsDcbStallCommandBufferParser);
|
||||
LIB_FUNC("3KDcnM3lrcU", Gen5::GraphicsWaitRegMemPatchAddress);
|
||||
LIB_FUNC("7nOoijNPvEU", Gen5::GraphicsWaitRegMemPatchReference);
|
||||
LIB_FUNC("0fWWK5uG9rQ", Gen5::GraphicsQueueEndOfPipeActionPatchAddress);
|
||||
LIB_FUNC("MlEw1feXcjg", Gen5::GraphicsQueueEndOfPipeActionPatchData);
|
||||
LIB_FUNC("ORWsxIbk4TE", Gen5::GraphicsCondExecPatchSetEnd);
|
||||
LIB_FUNC("YWTKOju587o", Gen5::GraphicsCondExecPatchSetCommandAddress);
|
||||
LIB_FUNC("k-JpyR2dYAM", Gen5::GraphicsCondExecPatchSetEnd);
|
||||
LIB_FUNC("3ZWa3AoyWZQ", Gen5::GraphicsCondExecPatchSetCommandAddress);
|
||||
LIB_FUNC("YUeqkyT7mEQ", Gen5::GraphicsDcbSetFlip);
|
||||
}
|
||||
|
||||
} // namespace LibGen5
|
||||
|
||||
namespace LibGen5Driver {
|
||||
|
||||
LIB_VERSION("Graphics5Driver", 1, "Graphics5Driver", 1, 1);
|
||||
|
||||
namespace Gen5Driver = Graphics::Gen5Driver;
|
||||
|
||||
LIB_DEFINE(InitGraphicsDriver_1) {
|
||||
PRINT_NAME_ENABLE(true);
|
||||
|
||||
LIB_FUNC("UglJIZjGssM", Gen5Driver::GraphicsDriverSubmitDcb);
|
||||
LIB_FUNC("AhGvpITrf4M", Gen5Driver::GraphicsDriverSubmitDcb);
|
||||
LIB_FUNC("6UzEidRZwkg", Gen5Driver::GraphicsDriverSubmitMultiDcbs);
|
||||
LIB_FUNC("+T8Xo6LtFJI", Gen5Driver::GraphicsDriverSubmitMultiDcbs);
|
||||
LIB_FUNC("b4fpgH5ZXxQ", Gen5Driver::GraphicsDriverSubmitCommandBuffer);
|
||||
LIB_FUNC("Fj7r9EHzF38", Gen5Driver::GraphicsDriverSubmitMultiCommandBuffers);
|
||||
LIB_FUNC("gSRnr79F8tQ", Gen5Driver::GraphicsDriverSubmitAcb);
|
||||
LIB_FUNC("HF3YllT3mXU", Gen5Driver::GraphicsDriverSubmitMultiAcbs);
|
||||
LIB_FUNC("w2rJhmD+dsE", Gen5Driver::GraphicsDriverAddEqEvent);
|
||||
LIB_FUNC("DL2RXaXOy88", Gen5Driver::GraphicsDriverDeleteEqEvent);
|
||||
LIB_FUNC("5CdQTZIQPxM", Gen5Driver::GraphicsDriverGetEqEventType);
|
||||
LIB_FUNC("Zw7uUVPulbw", Gen5Driver::GraphicsDriverGetEqContextId);
|
||||
LIB_FUNC("XlNp7jzGiPo", Gen5Driver::GraphicsDriverSetTFRing);
|
||||
LIB_FUNC("MM4IZSEYytQ", Gen5Driver::GraphicsDriverSetHsOffchipParam);
|
||||
LIB_FUNC("Ddwk4gLT5j0", Gen5Driver::GraphicsDriverIsCaptureInProgress);
|
||||
LIB_FUNC("U9ueyEhSkF4", Gen5Driver::GraphicsDriverUnknownU9ueyEhSkF4);
|
||||
}
|
||||
|
||||
} // namespace LibGen5Driver
|
||||
|
||||
LIB_DEFINE(InitGraphicsDriver_1) {
|
||||
LibGen5::InitGraphicsDriver_1(s);
|
||||
LibGen5Driver::InitGraphicsDriver_1(s);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,992 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibJson2 {
|
||||
|
||||
LIB_VERSION("Json2", 1, "Json2", 1, 1);
|
||||
|
||||
enum JsonValueType : uint32_t {
|
||||
JsonValueTypeNull = 0,
|
||||
JsonValueTypeBoolean,
|
||||
JsonValueTypeInteger,
|
||||
JsonValueTypeUInteger,
|
||||
JsonValueTypeReal,
|
||||
JsonValueTypeString,
|
||||
JsonValueTypeArray,
|
||||
JsonValueTypeObject,
|
||||
};
|
||||
|
||||
constexpr int32_t JSON_ERROR_PARSE_INVALID_CHAR = -2138799871; // 0x80848101
|
||||
constexpr int32_t JSON_ERROR_INVALID_ARGUMENT = -2138799840; // 0x80848120
|
||||
|
||||
struct JsonValue;
|
||||
|
||||
struct JsonString {
|
||||
std::string* impl;
|
||||
};
|
||||
|
||||
struct JsonArray {
|
||||
std::vector<JsonValue*>* impl;
|
||||
};
|
||||
|
||||
struct JsonObject {
|
||||
std::map<std::string, JsonValue*>* impl;
|
||||
};
|
||||
|
||||
struct JsonValue {
|
||||
JsonValue* parent;
|
||||
void* rootparam;
|
||||
union {
|
||||
bool boolean;
|
||||
int64_t integer;
|
||||
uint64_t uinteger;
|
||||
double real;
|
||||
JsonString* string;
|
||||
JsonArray* array;
|
||||
JsonObject* object;
|
||||
};
|
||||
char padding[4];
|
||||
uint32_t type;
|
||||
};
|
||||
|
||||
struct JsonInitParameter2 {
|
||||
void* allocator;
|
||||
void* user_data;
|
||||
size_t file_buffer_size;
|
||||
uint32_t special_float_format_type;
|
||||
uint32_t reserved[3];
|
||||
};
|
||||
|
||||
static std::string* JsonStringImpl(JsonString* self) {
|
||||
if (self == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (self->impl == nullptr) {
|
||||
self->impl = new std::string;
|
||||
}
|
||||
return self->impl;
|
||||
}
|
||||
|
||||
static const std::string* JsonStringImpl(const JsonString* self) {
|
||||
static const std::string empty;
|
||||
return (self != nullptr && self->impl != nullptr ? self->impl : &empty);
|
||||
}
|
||||
|
||||
static std::vector<JsonValue*>* JsonArrayImpl(JsonArray* self) {
|
||||
if (self == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (self->impl == nullptr) {
|
||||
self->impl = new std::vector<JsonValue*>;
|
||||
}
|
||||
return self->impl;
|
||||
}
|
||||
|
||||
static const std::vector<JsonValue*>* JsonArrayImpl(const JsonArray* self) {
|
||||
static const std::vector<JsonValue*> empty;
|
||||
return (self != nullptr && self->impl != nullptr ? self->impl : &empty);
|
||||
}
|
||||
|
||||
static std::map<std::string, JsonValue*>* JsonObjectImpl(JsonObject* self) {
|
||||
if (self == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (self->impl == nullptr) {
|
||||
self->impl = new std::map<std::string, JsonValue*>;
|
||||
}
|
||||
return self->impl;
|
||||
}
|
||||
|
||||
static const std::map<std::string, JsonValue*>* JsonObjectImpl(const JsonObject* self) {
|
||||
static const std::map<std::string, JsonValue*> empty;
|
||||
return (self != nullptr && self->impl != nullptr ? self->impl : &empty);
|
||||
}
|
||||
|
||||
static JsonValue* JsonStaticNullValue() {
|
||||
static JsonValue value {};
|
||||
value.type = JsonValueTypeNull;
|
||||
return &value;
|
||||
}
|
||||
|
||||
static JsonString* JsonStaticString() {
|
||||
static JsonString str {new std::string};
|
||||
return &str;
|
||||
}
|
||||
|
||||
static JsonArray* JsonStaticArray() {
|
||||
static JsonArray array {new std::vector<JsonValue*>};
|
||||
return &array;
|
||||
}
|
||||
|
||||
static JsonObject* JsonStaticObject() {
|
||||
static JsonObject object {new std::map<std::string, JsonValue*>};
|
||||
return &object;
|
||||
}
|
||||
|
||||
static void JsonValueInit(JsonValue* self) {
|
||||
if (self != nullptr) {
|
||||
std::memset(self, 0, sizeof(JsonValue));
|
||||
self->type = JsonValueTypeNull;
|
||||
}
|
||||
}
|
||||
|
||||
static void JsonValueClear(JsonValue* self);
|
||||
|
||||
static JsonValue* JsonValueNew() {
|
||||
auto* value = new JsonValue;
|
||||
JsonValueInit(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static JsonString* JsonStringNew(const std::string& value) {
|
||||
auto* str = new JsonString {};
|
||||
str->impl = new std::string(value);
|
||||
return str;
|
||||
}
|
||||
|
||||
static JsonArray* JsonArrayNew() {
|
||||
auto* array = new JsonArray {};
|
||||
array->impl = new std::vector<JsonValue*>;
|
||||
return array;
|
||||
}
|
||||
|
||||
static JsonObject* JsonObjectNew() {
|
||||
auto* object = new JsonObject {};
|
||||
object->impl = new std::map<std::string, JsonValue*>;
|
||||
return object;
|
||||
}
|
||||
|
||||
static void JsonValueDelete(JsonValue* self) {
|
||||
if (self != nullptr) {
|
||||
JsonValueClear(self);
|
||||
delete self;
|
||||
}
|
||||
}
|
||||
|
||||
static void JsonStringDelete(JsonString* self) {
|
||||
if (self != nullptr) {
|
||||
delete self->impl;
|
||||
delete self;
|
||||
}
|
||||
}
|
||||
|
||||
static void JsonArrayDelete(JsonArray* self) {
|
||||
if (self != nullptr) {
|
||||
if (self->impl != nullptr) {
|
||||
for (auto* value: *self->impl) {
|
||||
JsonValueDelete(value);
|
||||
}
|
||||
}
|
||||
delete self->impl;
|
||||
delete self;
|
||||
}
|
||||
}
|
||||
|
||||
static void JsonObjectDelete(JsonObject* self) {
|
||||
if (self != nullptr) {
|
||||
if (self->impl != nullptr) {
|
||||
for (auto& item: *self->impl) {
|
||||
JsonValueDelete(item.second);
|
||||
}
|
||||
}
|
||||
delete self->impl;
|
||||
delete self;
|
||||
}
|
||||
}
|
||||
|
||||
static void JsonValueClear(JsonValue* self) {
|
||||
if (self == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (self->type) {
|
||||
case JsonValueTypeString: JsonStringDelete(self->string); break;
|
||||
case JsonValueTypeArray: JsonArrayDelete(self->array); break;
|
||||
case JsonValueTypeObject: JsonObjectDelete(self->object); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
self->parent = nullptr;
|
||||
self->rootparam = nullptr;
|
||||
self->uinteger = 0;
|
||||
self->type = JsonValueTypeNull;
|
||||
}
|
||||
|
||||
static void JsonValueCopy(JsonValue* dst, const JsonValue* src) {
|
||||
if (dst == nullptr || src == nullptr || dst == src) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonValueClear(dst);
|
||||
dst->type = src->type;
|
||||
switch (src->type) {
|
||||
case JsonValueTypeBoolean: dst->boolean = src->boolean; break;
|
||||
case JsonValueTypeInteger: dst->integer = src->integer; break;
|
||||
case JsonValueTypeUInteger: dst->uinteger = src->uinteger; break;
|
||||
case JsonValueTypeReal: dst->real = src->real; break;
|
||||
case JsonValueTypeString: dst->string = JsonStringNew(*JsonStringImpl(src->string)); break;
|
||||
case JsonValueTypeArray: {
|
||||
dst->array = JsonArrayNew();
|
||||
for (auto* value: *JsonArrayImpl(src->array)) {
|
||||
auto* copy = JsonValueNew();
|
||||
JsonValueCopy(copy, value);
|
||||
copy->parent = dst;
|
||||
dst->array->impl->push_back(copy);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JsonValueTypeObject: {
|
||||
dst->object = JsonObjectNew();
|
||||
for (const auto& item: *JsonObjectImpl(src->object)) {
|
||||
auto* copy = JsonValueNew();
|
||||
JsonValueCopy(copy, item.second);
|
||||
copy->parent = dst;
|
||||
(*dst->object->impl)[item.first] = copy;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: dst->uinteger = 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
static JsonValue* JsonObjectLookup(JsonObject* object, const std::string& key, bool create) {
|
||||
auto* impl = JsonObjectImpl(object);
|
||||
if (impl == nullptr) {
|
||||
return JsonStaticNullValue();
|
||||
}
|
||||
auto it = impl->find(key);
|
||||
if (it != impl->end()) {
|
||||
return it->second;
|
||||
}
|
||||
if (!create) {
|
||||
return JsonStaticNullValue();
|
||||
}
|
||||
auto* value = JsonValueNew();
|
||||
(*impl)[key] = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool JsonValueFromNlohmann(JsonValue* out, const nlohmann::json& value) {
|
||||
if (out == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonValueClear(out);
|
||||
if (value.is_null()) {
|
||||
return true;
|
||||
}
|
||||
if (value.is_boolean()) {
|
||||
out->type = JsonValueTypeBoolean;
|
||||
out->boolean = value.get<bool>();
|
||||
return true;
|
||||
}
|
||||
if (value.is_number_integer() && !value.is_number_unsigned()) {
|
||||
out->type = JsonValueTypeInteger;
|
||||
out->integer = value.get<int64_t>();
|
||||
return true;
|
||||
}
|
||||
if (value.is_number_unsigned()) {
|
||||
out->type = JsonValueTypeUInteger;
|
||||
out->uinteger = value.get<uint64_t>();
|
||||
return true;
|
||||
}
|
||||
if (value.is_number_float()) {
|
||||
out->type = JsonValueTypeReal;
|
||||
out->real = value.get<double>();
|
||||
return true;
|
||||
}
|
||||
if (value.is_string()) {
|
||||
out->type = JsonValueTypeString;
|
||||
out->string = JsonStringNew(value.get_ref<const std::string&>());
|
||||
return true;
|
||||
}
|
||||
if (value.is_array()) {
|
||||
out->type = JsonValueTypeArray;
|
||||
out->array = JsonArrayNew();
|
||||
for (const auto& item: value) {
|
||||
auto* child = JsonValueNew();
|
||||
if (!JsonValueFromNlohmann(child, item)) {
|
||||
JsonValueDelete(child);
|
||||
return false;
|
||||
}
|
||||
child->parent = out;
|
||||
out->array->impl->push_back(child);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (value.is_object()) {
|
||||
out->type = JsonValueTypeObject;
|
||||
out->object = JsonObjectNew();
|
||||
for (auto it = value.begin(); it != value.end(); ++it) {
|
||||
auto* child = JsonValueNew();
|
||||
if (!JsonValueFromNlohmann(child, *it)) {
|
||||
JsonValueDelete(child);
|
||||
return false;
|
||||
}
|
||||
child->parent = out;
|
||||
(*out->object->impl)[it.key()] = child;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void JsonSerializeValue(const JsonValue* value, std::string* out) {
|
||||
if (value == nullptr) {
|
||||
out->append("null");
|
||||
return;
|
||||
}
|
||||
switch (value->type) {
|
||||
case JsonValueTypeBoolean: out->append(value->boolean ? "true" : "false"); break;
|
||||
case JsonValueTypeInteger: out->append(std::to_string(value->integer)); break;
|
||||
case JsonValueTypeUInteger: out->append(std::to_string(value->uinteger)); break;
|
||||
case JsonValueTypeReal: out->append(std::to_string(value->real)); break;
|
||||
case JsonValueTypeString:
|
||||
out->push_back('"');
|
||||
out->append(*JsonStringImpl(value->string));
|
||||
out->push_back('"');
|
||||
break;
|
||||
case JsonValueTypeArray: {
|
||||
out->push_back('[');
|
||||
bool first = true;
|
||||
for (auto* item: *JsonArrayImpl(value->array)) {
|
||||
if (!first) {
|
||||
out->push_back(',');
|
||||
}
|
||||
first = false;
|
||||
JsonSerializeValue(item, out);
|
||||
}
|
||||
out->push_back(']');
|
||||
break;
|
||||
}
|
||||
case JsonValueTypeObject: {
|
||||
out->push_back('{');
|
||||
bool first = true;
|
||||
for (const auto& item: *JsonObjectImpl(value->object)) {
|
||||
if (!first) {
|
||||
out->push_back(',');
|
||||
}
|
||||
first = false;
|
||||
out->push_back('"');
|
||||
out->append(item.first);
|
||||
out->append("\":");
|
||||
JsonSerializeValue(item.second, out);
|
||||
}
|
||||
out->push_back('}');
|
||||
break;
|
||||
}
|
||||
default: out->append("null"); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void* KYTY_SYSV_ABI JsonMemAllocatorCtor(void* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonInitParameter2* KYTY_SYSV_ABI JsonInitParameter2Ctor(JsonInitParameter2* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
self->allocator = nullptr;
|
||||
self->user_data = nullptr;
|
||||
self->file_buffer_size = 0;
|
||||
self->special_float_format_type = 0;
|
||||
self->reserved[0] = 0;
|
||||
self->reserved[1] = 0;
|
||||
self->reserved[2] = 0;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonInitParameter2SetAllocator(JsonInitParameter2* self, void* allocator,
|
||||
void* user_data) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
self->allocator = allocator;
|
||||
self->user_data = user_data;
|
||||
}
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonInitParameter2SetFileBufferSize(JsonInitParameter2* self,
|
||||
size_t size) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
self->file_buffer_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonInitParameter2SetSpecialFloatFormatType(JsonInitParameter2* self,
|
||||
uint32_t type) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
self->special_float_format_type = type;
|
||||
}
|
||||
}
|
||||
|
||||
static void* KYTY_SYSV_ABI JsonInitializerCtor(void* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI JsonInitializerInitialize(void* self,
|
||||
const JsonInitParameter2* init_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t self = 0x%016" PRIx64 "\n"
|
||||
"\t init_param = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(self), reinterpret_cast<uint64_t>(init_param));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI JsonInitializerInitializeV1(void* self, const void* init_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t self = 0x%016" PRIx64 "\n"
|
||||
"\t init_param = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(self), reinterpret_cast<uint64_t>(init_param));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonInitializerTerminate(void* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t self = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(self));
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonInitializerDtor(void* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t self = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(self));
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonMemAllocatorDtor(void* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t self = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(self));
|
||||
}
|
||||
|
||||
static void* KYTY_SYSV_ABI JsonValueCtor(void* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t self = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(self));
|
||||
|
||||
if (self != nullptr) {
|
||||
JsonValueInit(reinterpret_cast<JsonValue*>(self));
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonValueBoolCtor(JsonValue* self, bool value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueInit(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeBoolean;
|
||||
self->boolean = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonValueIntCtor(JsonValue* self, int64_t value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueInit(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeInteger;
|
||||
self->integer = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonValueDoubleCtor(JsonValue* self, double value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueInit(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeReal;
|
||||
self->real = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonValueCStringCtor(JsonValue* self, const char* value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueInit(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeString;
|
||||
self->string = JsonStringNew(value != nullptr ? value : "");
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonValueStringCtor(JsonValue* self, const JsonString* value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueInit(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeString;
|
||||
self->string = JsonStringNew(*JsonStringImpl(value));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonValueObjectCtor(JsonValue* self, const JsonObject* value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueInit(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeObject;
|
||||
self->object = JsonObjectNew();
|
||||
for (const auto& item: *JsonObjectImpl(value)) {
|
||||
auto* copy = JsonValueNew();
|
||||
JsonValueCopy(copy, item.second);
|
||||
(*self->object->impl)[item.first] = copy;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonValueDtor(void* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t self = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(self));
|
||||
|
||||
JsonValueClear(reinterpret_cast<JsonValue*>(self));
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonValueAssign(JsonValue* self, const JsonValue* src) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueCopy(self, src);
|
||||
return self;
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonValueSetBool(JsonValue* self, bool value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueClear(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeBoolean;
|
||||
self->boolean = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonValueSetInt(JsonValue* self, int64_t value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueClear(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeInteger;
|
||||
self->integer = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonValueSetUInt(JsonValue* self, uint64_t value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueClear(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeUInteger;
|
||||
self->uinteger = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonValueSetDouble(JsonValue* self, double value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueClear(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeReal;
|
||||
self->real = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonValueSetString(JsonValue* self, const JsonString* value) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueClear(self);
|
||||
if (self != nullptr) {
|
||||
self->type = JsonValueTypeString;
|
||||
self->string = JsonStringNew(*JsonStringImpl(value));
|
||||
}
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonValueSetType(JsonValue* self, uint32_t type) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonValueClear(self);
|
||||
if (self == nullptr) {
|
||||
return;
|
||||
}
|
||||
self->type = type;
|
||||
switch (type) {
|
||||
case JsonValueTypeString: self->string = JsonStringNew(""); break;
|
||||
case JsonValueTypeArray: self->array = JsonArrayNew(); break;
|
||||
case JsonValueTypeObject: self->object = JsonObjectNew(); break;
|
||||
default: self->uinteger = 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t KYTY_SYSV_ABI JsonValueGetType(const JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return (self != nullptr ? self->type : JsonValueTypeNull);
|
||||
}
|
||||
|
||||
static JsonArray* KYTY_SYSV_ABI JsonValueReferArray(JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return (self != nullptr && self->type == JsonValueTypeArray ? self->array : nullptr);
|
||||
}
|
||||
|
||||
static JsonObject* KYTY_SYSV_ABI JsonValueReferObject(JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return (self != nullptr && self->type == JsonValueTypeObject ? self->object : nullptr);
|
||||
}
|
||||
|
||||
static const JsonString* KYTY_SYSV_ABI JsonValueGetString(const JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return (self != nullptr && self->type == JsonValueTypeString ? self->string
|
||||
: JsonStaticString());
|
||||
}
|
||||
|
||||
static const JsonArray* KYTY_SYSV_ABI JsonValueGetArray(const JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return (self != nullptr && self->type == JsonValueTypeArray ? self->array : JsonStaticArray());
|
||||
}
|
||||
|
||||
static const JsonObject* KYTY_SYSV_ABI JsonValueGetObject(const JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return (self != nullptr && self->type == JsonValueTypeObject ? self->object
|
||||
: JsonStaticObject());
|
||||
}
|
||||
|
||||
static const bool* KYTY_SYSV_ABI JsonValueGetBoolean(const JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
static const bool false_value = false;
|
||||
return (self != nullptr && self->type == JsonValueTypeBoolean ? &self->boolean : &false_value);
|
||||
}
|
||||
|
||||
static const int64_t* KYTY_SYSV_ABI JsonValueGetInteger(const JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
static const int64_t zero = 0;
|
||||
return (self != nullptr && self->type == JsonValueTypeInteger ? &self->integer : &zero);
|
||||
}
|
||||
|
||||
static const double* KYTY_SYSV_ABI JsonValueGetReal(const JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
static const double zero = 0.0;
|
||||
return (self != nullptr && self->type == JsonValueTypeReal ? &self->real : &zero);
|
||||
}
|
||||
|
||||
static const JsonValue* KYTY_SYSV_ABI JsonValueIndexString(const JsonValue* self, const char* key) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self == nullptr || self->type != JsonValueTypeObject) {
|
||||
return JsonStaticNullValue();
|
||||
}
|
||||
return JsonObjectLookup(self->object, key != nullptr ? key : "", false);
|
||||
}
|
||||
|
||||
static const JsonValue* KYTY_SYSV_ABI JsonValueIndexUInt(const JsonValue* self, uint64_t index) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self == nullptr || self->type != JsonValueTypeArray) {
|
||||
return JsonStaticNullValue();
|
||||
}
|
||||
const auto* impl = JsonArrayImpl(self->array);
|
||||
return (index < impl->size() ? (*impl)[static_cast<size_t>(index)] : JsonStaticNullValue());
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI JsonValueSerialize(JsonValue* self, JsonString* dst) {
|
||||
PRINT_NAME();
|
||||
|
||||
auto* impl = JsonStringImpl(dst);
|
||||
if (impl != nullptr) {
|
||||
impl->clear();
|
||||
JsonSerializeValue(self, impl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static JsonString* KYTY_SYSV_ABI JsonStringCtor(JsonString* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
self->impl = new std::string;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonString* KYTY_SYSV_ABI JsonStringCStringCtor(JsonString* self, const char* str) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
self->impl = new std::string(str != nullptr ? str : "");
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonStringDtor(JsonString* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
delete self->impl;
|
||||
self->impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static JsonString* KYTY_SYSV_ABI JsonStringAssign(JsonString* self, const JsonString* src) {
|
||||
PRINT_NAME();
|
||||
|
||||
auto* impl = JsonStringImpl(self);
|
||||
if (impl != nullptr) {
|
||||
*impl = *JsonStringImpl(src);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static const char* KYTY_SYSV_ABI JsonStringCStr(const JsonString* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return JsonStringImpl(self)->c_str();
|
||||
}
|
||||
|
||||
static size_t KYTY_SYSV_ABI JsonStringLength(const JsonString* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return JsonStringImpl(self)->length();
|
||||
}
|
||||
|
||||
static JsonArray* KYTY_SYSV_ABI JsonArrayPushBack(JsonArray* self, const JsonValue* value) {
|
||||
PRINT_NAME();
|
||||
|
||||
auto* impl = JsonArrayImpl(self);
|
||||
if (impl != nullptr) {
|
||||
auto* copy = JsonValueNew();
|
||||
JsonValueCopy(copy, value);
|
||||
impl->push_back(copy);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonArrayBack(const JsonArray* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto* impl = JsonArrayImpl(self);
|
||||
return (!impl->empty() ? impl->back() : JsonStaticNullValue());
|
||||
}
|
||||
|
||||
static size_t KYTY_SYSV_ABI JsonArraySize(const JsonArray* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
return JsonArrayImpl(self)->size();
|
||||
}
|
||||
|
||||
static JsonObject* KYTY_SYSV_ABI JsonObjectCtor(JsonObject* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
self->impl = new std::map<std::string, JsonValue*>;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonObject* KYTY_SYSV_ABI JsonObjectCopyCtor(JsonObject* self, const JsonObject* src) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
self->impl = new std::map<std::string, JsonValue*>;
|
||||
for (const auto& item: *JsonObjectImpl(src)) {
|
||||
auto* copy = JsonValueNew();
|
||||
JsonValueCopy(copy, item.second);
|
||||
(*self->impl)[item.first] = copy;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonObjectDtor(JsonObject* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self != nullptr) {
|
||||
if (self->impl != nullptr) {
|
||||
for (auto& item: *self->impl) {
|
||||
JsonValueDelete(item.second);
|
||||
}
|
||||
self->impl->clear();
|
||||
}
|
||||
delete self->impl;
|
||||
self->impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static JsonObject* KYTY_SYSV_ABI JsonObjectAssign(JsonObject* self, const JsonObject* src) {
|
||||
PRINT_NAME();
|
||||
|
||||
JsonObjectDtor(self);
|
||||
JsonObjectCopyCtor(self, src);
|
||||
return self;
|
||||
}
|
||||
|
||||
static JsonValue* KYTY_SYSV_ABI JsonObjectIndex(JsonObject* self, const JsonString* key) {
|
||||
PRINT_NAME();
|
||||
|
||||
return JsonObjectLookup(self, *JsonStringImpl(key), true);
|
||||
}
|
||||
|
||||
static void KYTY_SYSV_ABI JsonObjectClear(JsonObject* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
auto* impl = JsonObjectImpl(self);
|
||||
if (impl != nullptr) {
|
||||
for (auto& item: *impl) {
|
||||
JsonValueDelete(item.second);
|
||||
}
|
||||
impl->clear();
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI JsonParserParse(JsonValue* dst, const char* src, size_t size) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (dst == nullptr || src == nullptr) {
|
||||
return JSON_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
JsonValue parsed {};
|
||||
JsonValueInit(&parsed);
|
||||
auto json = nlohmann::json::parse(src, src + size, nullptr, false);
|
||||
if (json.is_discarded() || !JsonValueFromNlohmann(&parsed, json)) {
|
||||
JsonValueClear(&parsed);
|
||||
return JSON_ERROR_PARSE_INVALID_CHAR;
|
||||
}
|
||||
|
||||
JsonValueCopy(dst, &parsed);
|
||||
JsonValueClear(&parsed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI JsonInitializerSetGlobalNullAccessCallback(void* self, void* callback,
|
||||
void* context) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t self = 0x%016" PRIx64 "\n"
|
||||
"\t callback = 0x%016" PRIx64 "\n"
|
||||
"\t context = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(self), reinterpret_cast<uint64_t>(callback),
|
||||
reinterpret_cast<uint64_t>(context));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI JsonValueCount(const JsonValue* self) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (self == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (self->type) {
|
||||
case JsonValueTypeArray: return static_cast<int32_t>(JsonArrayImpl(self->array)->size());
|
||||
case JsonValueTypeObject: return static_cast<int32_t>(JsonObjectImpl(self->object)->size());
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitNet_1_Json2) {
|
||||
LIB_FUNC("-hJRce8wn1U", LibJson2::JsonMemAllocatorCtor);
|
||||
LIB_FUNC("WSOuge5IsCg", LibJson2::JsonInitParameter2Ctor);
|
||||
LIB_FUNC("GvGvswb0v34", LibJson2::JsonInitParameter2Ctor);
|
||||
LIB_FUNC("I2QC8PYhJWY", LibJson2::JsonInitParameter2SetAllocator);
|
||||
LIB_FUNC("W72B9ylU2JA", LibJson2::JsonInitParameter2SetAllocator);
|
||||
LIB_FUNC("Eu95jmqn5Rw", LibJson2::JsonInitParameter2SetFileBufferSize);
|
||||
LIB_FUNC("WVZBP4IyM+E", LibJson2::JsonInitParameter2SetSpecialFloatFormatType);
|
||||
LIB_FUNC("cK6bYHf-Q5E", LibJson2::JsonInitializerCtor);
|
||||
LIB_FUNC("IXW-z8pggfg", LibJson2::JsonInitializerInitialize);
|
||||
LIB_FUNC("Cxwy7wHq4J0", LibJson2::JsonInitializerInitializeV1);
|
||||
LIB_FUNC("PR5k1penBLM", LibJson2::JsonInitializerTerminate);
|
||||
LIB_FUNC("RujUxbr3haM", LibJson2::JsonInitializerDtor);
|
||||
LIB_FUNC("OcAgPxcq5Vk", LibJson2::JsonMemAllocatorDtor);
|
||||
LIB_FUNC("qBMjqyBn3OM", LibJson2::JsonValueCtor);
|
||||
LIB_FUNC("-wa17B7TGnw", LibJson2::JsonValueCtor);
|
||||
LIB_FUNC("WTtYf+cNnXI", LibJson2::JsonValueDtor);
|
||||
LIB_FUNC("0eUrW9JAxM0", LibJson2::JsonValueDtor);
|
||||
LIB_FUNC("S5JxQnoGF3E", LibJson2::JsonParserParse);
|
||||
LIB_FUNC("HwDt5lD9Bfo", LibJson2::JsonValueIndexString);
|
||||
LIB_FUNC("epJ6x2LV0kU", LibJson2::JsonValueGetString);
|
||||
LIB_FUNC("L1KAkYWml-M", LibJson2::JsonStringCStr);
|
||||
LIB_FUNC("OJPTonqdg0I", LibJson2::JsonObjectCtor);
|
||||
LIB_FUNC("sZIoMRGO+jk", LibJson2::JsonValueStringCtor);
|
||||
LIB_FUNC("ERuf9y0DY84", LibJson2::JsonObjectIndex);
|
||||
LIB_FUNC("4zrm6VrgIAw", LibJson2::JsonValueAssign);
|
||||
LIB_FUNC("a+W7HHlwpBs", LibJson2::JsonObjectCopyCtor);
|
||||
LIB_FUNC("5JmzZt8twAo", LibJson2::JsonObjectDtor);
|
||||
LIB_FUNC("nM5XqdeXFPw", LibJson2::JsonValueReferArray);
|
||||
LIB_FUNC("-NxEk7XLkDY", LibJson2::JsonValueReferObject);
|
||||
LIB_FUNC("zQtLRTqceMY", LibJson2::JsonArrayPushBack);
|
||||
LIB_FUNC("0lLK8+kDqmE", LibJson2::JsonValueIntCtor);
|
||||
LIB_FUNC("urOpESTBZmo", LibJson2::JsonObjectAssign);
|
||||
LIB_FUNC("zTwZdI8AZ5Y", LibJson2::JsonValueGetBoolean);
|
||||
LIB_FUNC("R7FDWtcN6f8", LibJson2::JsonValueSerialize);
|
||||
LIB_FUNC("oH8aBmLU+fc", LibJson2::JsonObjectClear);
|
||||
LIB_FUNC("bAM9Qwofus0", LibJson2::JsonArrayBack);
|
||||
LIB_FUNC("UeuWT+yNdCQ", LibJson2::JsonValueBoolCtor);
|
||||
LIB_FUNC("3xUXnmUkXfo", LibJson2::JsonValueObjectCtor);
|
||||
LIB_FUNC("cn9svYGWKDQ", LibJson2::JsonStringAssign);
|
||||
LIB_FUNC("b9V6fmppLXY", LibJson2::JsonValueCStringCtor);
|
||||
LIB_FUNC("EUH+EmT-v9E", LibJson2::JsonStringLength);
|
||||
LIB_FUNC("XlWbvieLj2M", LibJson2::JsonValueIndexUInt);
|
||||
LIB_FUNC("IlsmvBtMkak", LibJson2::JsonValueGetObject);
|
||||
LIB_FUNC("SHtAad20YYM", LibJson2::JsonValueGetType);
|
||||
LIB_FUNC("DIxvoy7Ngvk", LibJson2::JsonValueGetInteger);
|
||||
LIB_FUNC("qSmqLXXCPas", LibJson2::JsonStringCtor);
|
||||
LIB_FUNC("ONT8As5R1ug", LibJson2::JsonValueGetArray);
|
||||
LIB_FUNC("3qrge7L-AU4", LibJson2::JsonValueGetReal);
|
||||
LIB_FUNC("sOmU4vnx3s0", LibJson2::JsonValueDoubleCtor);
|
||||
LIB_FUNC("rQGJeNjOuUk", LibJson2::JsonArraySize);
|
||||
LIB_FUNC("5yHuiWXo2gg", LibJson2::JsonValueSetBool);
|
||||
LIB_FUNC("QxVVYhP-mvg", LibJson2::JsonValueSetInt);
|
||||
LIB_FUNC("SIe1ZmW7e7s", LibJson2::JsonValueSetUInt);
|
||||
LIB_FUNC("BSmWDIkV4w4", LibJson2::JsonValueSetDouble);
|
||||
LIB_FUNC("6l3Bv2gysNc", LibJson2::JsonValueSetString);
|
||||
LIB_FUNC("9KUZFjI1IxA", LibJson2::JsonStringCStringCtor);
|
||||
LIB_FUNC("cG1VE2HMl6c", LibJson2::JsonStringDtor);
|
||||
LIB_FUNC("IKQimvG9Wqs", LibJson2::JsonValueSetType);
|
||||
LIB_FUNC("RBw+4NukeGQ", LibJson2::JsonValueCount);
|
||||
LIB_FUNC("+drDFyAS6u4", LibJson2::JsonInitializerSetGlobalNullAccessCallback);
|
||||
LIB_FUNC("00oCq0RwSAY", LibJson2::JsonInitializerSetGlobalNullAccessCallback);
|
||||
}
|
||||
|
||||
} // namespace LibJson2
|
||||
|
||||
} // namespace Libs
|
||||
File diff suppressed because it is too large.
Load diff
+3982
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,444 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/controller.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "libs/padData.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("Pad", 1, "Pad", 1, 1);
|
||||
|
||||
static int KYTY_SYSV_ABI PadSetVibrationMode(int handle, int mode) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t mode = %d\n",
|
||||
handle, mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct PadTriggerEffectStateInformation {
|
||||
int32_t state[2];
|
||||
};
|
||||
|
||||
static int KYTY_SYSV_ABI PadGetTriggerEffectState(int handle,
|
||||
PadTriggerEffectStateInformation* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n", handle);
|
||||
|
||||
if (info == nullptr) {
|
||||
return -2137653243; /* 0x80960005 */
|
||||
}
|
||||
|
||||
info->state[0] = 0;
|
||||
info->state[1] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadSetTriggerEffect(int handle, const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t param = 0x%016" PRIx64 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(param));
|
||||
|
||||
if (handle != 1) {
|
||||
return -2137915389; /* 0x80920003 */
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return -2137915391; /* 0x80920001 */
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse(bool enabled) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t enabled = %d\n", enabled ? 1 : 0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
struct PadDeviceClassExtendedInformation {
|
||||
int32_t device_class;
|
||||
uint8_t reserved[4];
|
||||
uint8_t class_data[12];
|
||||
};
|
||||
|
||||
struct PadDeviceClassData {
|
||||
int32_t device_class;
|
||||
bool data_valid;
|
||||
uint8_t reserved[3];
|
||||
union {
|
||||
struct {
|
||||
float steering_wheel_angle;
|
||||
uint16_t steering_wheel;
|
||||
uint16_t accelerator_pedal;
|
||||
uint16_t brake_pedal;
|
||||
uint16_t clutch_pedal;
|
||||
uint16_t hand_brake;
|
||||
uint8_t gear;
|
||||
uint8_t reserved[1];
|
||||
} steering_wheel;
|
||||
struct {
|
||||
uint8_t data_len;
|
||||
uint8_t reserved[3];
|
||||
uint8_t data[12];
|
||||
} others;
|
||||
uint8_t raw[16];
|
||||
} class_data;
|
||||
};
|
||||
|
||||
static_assert(sizeof(PadDeviceClassData) == 24);
|
||||
|
||||
static int KYTY_SYSV_ABI
|
||||
PadDeviceClassGetExtendedInformation(int handle, PadDeviceClassExtendedInformation* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
constexpr int pad_error_invalid_handle = -2137915389; /* 0x80920003 */
|
||||
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
||||
|
||||
if (handle != 1) {
|
||||
return pad_error_invalid_handle;
|
||||
}
|
||||
if (info == nullptr) {
|
||||
return pad_error_invalid_arg;
|
||||
}
|
||||
|
||||
std::memset(info, 0, sizeof(*info));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadDeviceClassParseData(int handle, const Controller::PadData* data,
|
||||
PadDeviceClassData* class_data) {
|
||||
PRINT_NAME();
|
||||
|
||||
constexpr int pad_error_invalid_handle = -2137915389; /* 0x80920003 */
|
||||
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t data = 0x%016" PRIx64 "\n"
|
||||
"\t class_data = 0x%016" PRIx64 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(data), reinterpret_cast<uint64_t>(class_data));
|
||||
|
||||
if (handle != 1) {
|
||||
return pad_error_invalid_handle;
|
||||
}
|
||||
if (data == nullptr || class_data == nullptr) {
|
||||
return pad_error_invalid_arg;
|
||||
}
|
||||
|
||||
std::memset(class_data, 0, sizeof(*class_data));
|
||||
class_data->device_class = 0; // SCE_PAD_DEVICE_CLASS_STANDARD
|
||||
class_data->data_valid = data->connected;
|
||||
|
||||
if (data->device_unique_data_len > 0) {
|
||||
const auto data_len =
|
||||
(data->device_unique_data_len > 12 ? 12 : data->device_unique_data_len);
|
||||
class_data->device_class = -1; // SCE_PAD_DEVICE_CLASS_INVALID/unsupported device payload
|
||||
class_data->class_data.others.data_len = data_len;
|
||||
std::memcpy(class_data->class_data.others.data, data->device_unique_data, data_len);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadSetTiltCorrectionState(int handle, bool enabled) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t enabled = %d\n",
|
||||
handle, enabled ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadClose(int handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n", handle);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadUnknownN3kSX62fgNo(uint64_t arg0, uint64_t arg1, uint64_t arg2,
|
||||
uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t argc-style args = (0x%016" PRIx64 ", 0x%016" PRIx64 ", 0x%016" PRIx64 ", 0x%016" PRIx64
|
||||
", 0x%016" PRIx64 ", 0x%016" PRIx64 ")\n",
|
||||
arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
|
||||
if (arg0 >= 0x10000 && arg3 > 0 && arg3 <= 0x1000) {
|
||||
std::memset(reinterpret_cast<void*>(arg0), 0, static_cast<size_t>(arg3));
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitPad_1) {
|
||||
PRINT_NAME_ENABLE(true);
|
||||
|
||||
LIB_FUNC("hv1luiJrqQM", Controller::PadInit);
|
||||
LIB_FUNC("xk0AcarP3V4", Controller::PadOpen);
|
||||
LIB_FUNC("u1GRHp+oWoY", Controller::PadGetHandle);
|
||||
LIB_FUNC("AcslpN1jHR8", PadDeviceClassGetExtendedInformation);
|
||||
LIB_FUNC("IHPqcbc0zCA", PadDeviceClassParseData);
|
||||
LIB_FUNC("clVvL4ZDntw", Controller::PadSetMotionSensorState);
|
||||
LIB_FUNC("r44mAxdSG+U", Controller::PadSetAngularVelocityDeadbandState);
|
||||
LIB_FUNC("rIZnR6eSpvk", Controller::PadResetOrientation);
|
||||
LIB_FUNC("vDLMoJLde8I", PadSetTiltCorrectionState);
|
||||
LIB_FUNC("gjP9-KQzoUk", Controller::PadGetControllerInformation);
|
||||
LIB_FUNC("2JgFB2n9oUM", PadSetTriggerEffect);
|
||||
LIB_FUNC("YndgXqQVV7c", Controller::PadReadState);
|
||||
LIB_FUNC("q1cHNfGycLI", Controller::PadRead);
|
||||
LIB_FUNC("yFVnOdGxvZY", Controller::PadSetVibration);
|
||||
LIB_FUNC("W2G-yoyMF5U", PadSetVibrationMode);
|
||||
LIB_FUNC("Yq0zOH7YNOM", PadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse);
|
||||
LIB_FUNC("znaWI0gpuo8", PadGetTriggerEffectState);
|
||||
LIB_FUNC("DscD1i9HX1w", Controller::PadResetLightBar);
|
||||
LIB_FUNC("RR4novUEENY", Controller::PadSetLightBar);
|
||||
LIB_FUNC("6ncge5+l5Qs", PadClose);
|
||||
LIB_FUNC("n3kSX62fgNo", PadUnknownN3kSX62fgNo);
|
||||
}
|
||||
|
||||
namespace LibMouse {
|
||||
|
||||
LIB_VERSION("Mouse", 1, "Mouse", 1, 1);
|
||||
|
||||
namespace Mouse {
|
||||
|
||||
constexpr int MOUSE_ERROR_INVALID_ARG = -2132869119; /* 0x80DF0001 */
|
||||
constexpr int MOUSE_ERROR_INVALID_HANDLE = -2132869117; /* 0x80DF0003 */
|
||||
|
||||
struct MouseData {
|
||||
uint64_t timestamp;
|
||||
bool connected;
|
||||
uint8_t padding[3];
|
||||
uint32_t buttons;
|
||||
int32_t x_axis;
|
||||
int32_t y_axis;
|
||||
int32_t wheel;
|
||||
int32_t tilt;
|
||||
uint8_t reserved[8];
|
||||
};
|
||||
|
||||
static int KYTY_SYSV_ABI MouseInit() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI MouseOpen(int user_id, int32_t type, int32_t index, const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t user_id = %d\n"
|
||||
"\t type = %" PRId32 "\n"
|
||||
"\t index = %" PRId32 "\n"
|
||||
"\t param = 0x%016" PRIx64 "\n",
|
||||
user_id, type, index, reinterpret_cast<uint64_t>(param));
|
||||
|
||||
if (type != 0 || index < 0 || index >= 2) {
|
||||
return MOUSE_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI MouseClose(int32_t handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %" PRId32 "\n", handle);
|
||||
|
||||
if (handle <= 0) {
|
||||
return MOUSE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI MouseRead(int32_t handle, MouseData* data, int32_t num) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %" PRId32 "\n"
|
||||
"\t data = 0x%016" PRIx64 "\n"
|
||||
"\t num = %" PRId32 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(data), num);
|
||||
|
||||
if (handle <= 0) {
|
||||
return MOUSE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (data == nullptr || num <= 0) {
|
||||
return MOUSE_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::memset(data, 0, sizeof(MouseData) * static_cast<size_t>(num));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Mouse
|
||||
|
||||
LIB_DEFINE(InitMouse_1) {
|
||||
LIB_FUNC("cAnT0Rw-IwU", Mouse::MouseClose);
|
||||
LIB_FUNC("Qs0wWulgl7U", Mouse::MouseInit);
|
||||
LIB_FUNC("RaqxZIf6DvE", Mouse::MouseOpen);
|
||||
LIB_FUNC("x8qnXqh-tiM", Mouse::MouseRead);
|
||||
}
|
||||
|
||||
} // namespace LibMouse
|
||||
|
||||
namespace LibKeyboard {
|
||||
|
||||
LIB_VERSION("Keyboard", 1, "Keyboard", 1, 1);
|
||||
|
||||
namespace Keyboard {
|
||||
|
||||
constexpr int KEYBOARD_ERROR_INVALID_ARG = -2133196799; /* 0x80da0001 */
|
||||
constexpr int KEYBOARD_ERROR_INVALID_HANDLE = -2133196797; /* 0x80da0003 */
|
||||
constexpr int KEYBOARD_MAX_KEYCODES = 16;
|
||||
constexpr int KEYBOARD_MAX_DATA_NUM = 16;
|
||||
constexpr int KEYBOARD_MAPPING_101 = 0;
|
||||
constexpr int KEYBOARD_MAPPING_106 = 1;
|
||||
|
||||
struct KeyboardData {
|
||||
uint64_t timestamp;
|
||||
bool intercepted;
|
||||
uint8_t reserve1[7];
|
||||
bool connected;
|
||||
int32_t length;
|
||||
uint32_t led;
|
||||
uint32_t modifier_key;
|
||||
uint16_t key_code[KEYBOARD_MAX_KEYCODES];
|
||||
uint8_t reserve2[32];
|
||||
};
|
||||
|
||||
struct KeyboardCharData {
|
||||
bool processed;
|
||||
int32_t length;
|
||||
uint16_t char_code;
|
||||
uint8_t reserve[8];
|
||||
};
|
||||
|
||||
static int KYTY_SYSV_ABI KeyboardInit() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI KeyboardOpen(int user_id, int32_t type, int32_t index, const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t user_id = %d\n"
|
||||
"\t type = %" PRId32 "\n"
|
||||
"\t index = %" PRId32 "\n"
|
||||
"\t param = 0x%016" PRIx64 "\n",
|
||||
user_id, type, index, reinterpret_cast<uint64_t>(param));
|
||||
|
||||
if (type != 0 || index < 0 || index >= 2) {
|
||||
return KEYBOARD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI KeyboardClose(int32_t handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %" PRId32 "\n", handle);
|
||||
|
||||
if (handle <= 0) {
|
||||
return KEYBOARD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI KeyboardRead(int32_t handle, KeyboardData* data, int32_t num) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %" PRId32 "\n"
|
||||
"\t data = 0x%016" PRIx64 "\n"
|
||||
"\t num = %" PRId32 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(data), num);
|
||||
|
||||
if (handle <= 0) {
|
||||
return KEYBOARD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (data == nullptr || num <= 0 || num > KEYBOARD_MAX_DATA_NUM) {
|
||||
return KEYBOARD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::memset(data, 0, sizeof(KeyboardData) * static_cast<size_t>(num));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI KeyboardReadState(int32_t handle, KeyboardData* data) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %" PRId32 "\n"
|
||||
"\t data = 0x%016" PRIx64 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(data));
|
||||
|
||||
if (handle <= 0) {
|
||||
return KEYBOARD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (data == nullptr) {
|
||||
return KEYBOARD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::memset(data, 0, sizeof(KeyboardData));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI KeyboardGetKey2Char(int32_t handle, int32_t arrange, uint32_t led,
|
||||
uint32_t modifier_key, uint16_t key_code,
|
||||
KeyboardCharData* char_data) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %" PRId32 "\n"
|
||||
"\t arrange = %" PRId32 "\n"
|
||||
"\t led = %" PRIu32 "\n"
|
||||
"\t modifier_key = %" PRIu32 "\n"
|
||||
"\t key_code = %" PRIu16 "\n"
|
||||
"\t char_data = 0x%016" PRIx64 "\n",
|
||||
handle, arrange, led, modifier_key, key_code, reinterpret_cast<uint64_t>(char_data));
|
||||
|
||||
if (handle <= 0) {
|
||||
return KEYBOARD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (char_data == nullptr ||
|
||||
(arrange != KEYBOARD_MAPPING_101 && arrange != KEYBOARD_MAPPING_106)) {
|
||||
return KEYBOARD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::memset(char_data, 0, sizeof(KeyboardCharData));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace Keyboard
|
||||
|
||||
LIB_DEFINE(InitKeyboard_1) {
|
||||
LIB_FUNC("wadT3QBCGY0", Keyboard::KeyboardInit);
|
||||
LIB_FUNC("HJ+KnEHcaxI", Keyboard::KeyboardOpen);
|
||||
LIB_FUNC("0LWei+c7RNc", Keyboard::KeyboardClose);
|
||||
LIB_FUNC("6HpE68bzX6M", Keyboard::KeyboardReadState);
|
||||
LIB_FUNC("xybbGMCr738", Keyboard::KeyboardRead);
|
||||
LIB_FUNC("yO9JwdRhtSA", Keyboard::KeyboardGetKey2Char);
|
||||
}
|
||||
|
||||
} // namespace LibKeyboard
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,458 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
#include "loader/systemContent.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("PlayGo", 1, "PlayGo", 1, 0);
|
||||
|
||||
namespace PlayGo {
|
||||
|
||||
static constexpr int PLAYGO_HANDLE = 1;
|
||||
static constexpr int8_t PLAYGO_LOCUS_NOT_DOWNLOADED = 0;
|
||||
static constexpr int8_t PLAYGO_LOCUS_LOCAL_SLOW = 2;
|
||||
static constexpr int8_t PLAYGO_LOCUS_LOCAL_FAST = 3;
|
||||
static constexpr int32_t PLAYGO_INSTALL_SPEED_FULL = 2;
|
||||
static constexpr int32_t PLAYGO_OPTIONAL_TYPE_LANGUAGE = 0;
|
||||
static constexpr int32_t PLAYGO_OPTIONAL_TYPE_SCENARIO = 1;
|
||||
static constexpr uint64_t PLAYGO_LANGUAGE_MASK_ALL = 0xffffffffffffffffull;
|
||||
static constexpr uint64_t PLAYGO_SCENARIO_MASK_ALL = 0x1full;
|
||||
|
||||
static uint32_t g_chunks_num = 0;
|
||||
|
||||
struct PlayGoInitParams {
|
||||
const void* buf_addr;
|
||||
uint32_t buf_size;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
struct PlayGoToDo {
|
||||
uint16_t chunk_id;
|
||||
int8_t locus;
|
||||
int8_t reserved;
|
||||
};
|
||||
|
||||
struct PlayGoProgress {
|
||||
uint64_t progress_size;
|
||||
uint64_t total_size;
|
||||
};
|
||||
|
||||
union PlayGoOptionalChunk {
|
||||
uint64_t bitmask;
|
||||
uint64_t languages;
|
||||
uint64_t scenarios;
|
||||
};
|
||||
|
||||
static bool ensure_chunks_loaded() {
|
||||
if (g_chunks_num != 0) {
|
||||
return true;
|
||||
}
|
||||
if (!Loader::SystemContentGetChunksNum(&g_chunks_num)) {
|
||||
LOGF("Warning: assume that chunks count is 1\n");
|
||||
g_chunks_num = 1;
|
||||
}
|
||||
return g_chunks_num != 0;
|
||||
}
|
||||
|
||||
static bool is_valid_chunk(uint16_t chunk_id) {
|
||||
return ensure_chunks_loaded() && chunk_id < g_chunks_num;
|
||||
}
|
||||
|
||||
static bool is_valid_locus(int8_t locus) {
|
||||
return locus == PLAYGO_LOCUS_NOT_DOWNLOADED || locus == PLAYGO_LOCUS_LOCAL_SLOW ||
|
||||
locus == PLAYGO_LOCUS_LOCAL_FAST;
|
||||
}
|
||||
|
||||
static int validate_handle(int handle) {
|
||||
return (handle == PLAYGO_HANDLE ? OK : PLAYGO_ERROR_BAD_HANDLE);
|
||||
}
|
||||
|
||||
static int validate_optional_type(int32_t type) {
|
||||
return (type == PLAYGO_OPTIONAL_TYPE_LANGUAGE || type == PLAYGO_OPTIONAL_TYPE_SCENARIO
|
||||
? OK
|
||||
: PLAYGO_ERROR_BAD_OPTIONAL_TYPE);
|
||||
}
|
||||
|
||||
static void set_optional_chunk(int32_t type, PlayGoOptionalChunk* option) {
|
||||
EXIT_IF(option == nullptr);
|
||||
|
||||
option->bitmask = (type == PLAYGO_OPTIONAL_TYPE_LANGUAGE ? PLAYGO_LANGUAGE_MASK_ALL
|
||||
: PLAYGO_SCENARIO_MASK_ALL);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoInitialize(const PlayGoInitParams* init) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (init == nullptr || init->buf_addr == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (init->buf_size < 2u * 1024u * 1024u) {
|
||||
return PLAYGO_ERROR_BAD_SIZE;
|
||||
}
|
||||
|
||||
LOGF("\t buf_addr = %016" PRIx64 "\n"
|
||||
"\t buf_size = %" PRIu32 "\n"
|
||||
"\t reserved = %" PRId32 "\n",
|
||||
reinterpret_cast<uint64_t>(init->buf_addr), init->buf_size, init->reserved);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoTerminate() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoOpen(int* out_handle, const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (out_handle == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (param != nullptr) {
|
||||
return PLAYGO_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*out_handle = PLAYGO_HANDLE;
|
||||
|
||||
ensure_chunks_loaded();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoClose(int handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetLocus(int handle, const uint16_t* chunk_ids, uint32_t number_of_entries,
|
||||
int8_t* out_loci) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n", handle);
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (chunk_ids == nullptr || out_loci == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (number_of_entries == 0) {
|
||||
return PLAYGO_ERROR_BAD_SIZE;
|
||||
}
|
||||
ensure_chunks_loaded();
|
||||
|
||||
for (uint32_t i = 0; i < number_of_entries; i++) {
|
||||
LOGF("\t chunk_ids[%u] = %" PRIu16 "\n", i, chunk_ids[i]);
|
||||
|
||||
if (is_valid_chunk(chunk_ids[i])) {
|
||||
out_loci[i] = PLAYGO_LOCUS_LOCAL_FAST;
|
||||
} else {
|
||||
return PLAYGO_ERROR_BAD_CHUNK_ID;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetInstallSpeed(int handle, int32_t* out_speed) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n", handle);
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (out_speed == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
|
||||
*out_speed = PLAYGO_INSTALL_SPEED_FULL;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoSetInstallSpeed(int handle, int32_t speed) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t speed = %" PRId32 "\n",
|
||||
handle, speed);
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (speed < 0 || speed > 2) {
|
||||
return PLAYGO_ERROR_BAD_SPEED;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetChunkId(int handle, uint16_t* out_chunk_id_list,
|
||||
uint32_t number_of_entries, uint32_t* out_entries) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t out_chunk_id_list = 0x%016" PRIx64 "\n"
|
||||
"\t number_of_entries = %" PRIu32 "\n"
|
||||
"\t out_entries = 0x%016" PRIx64 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(out_chunk_id_list), number_of_entries,
|
||||
reinterpret_cast<uint64_t>(out_entries));
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (out_entries == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (number_of_entries != 0 && out_chunk_id_list == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
ensure_chunks_loaded();
|
||||
|
||||
const uint32_t entries = std::min(number_of_entries, g_chunks_num);
|
||||
for (uint32_t i = 0; i < entries; i++) {
|
||||
out_chunk_id_list[i] = static_cast<uint16_t>(i);
|
||||
}
|
||||
*out_entries = entries;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetToDoList(int handle, PlayGoToDo* out_todo_list,
|
||||
uint32_t number_of_entries, uint32_t* out_entries) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t out_todo_list = 0x%016" PRIx64 "\n"
|
||||
"\t number_of_entries = %" PRIu32 "\n"
|
||||
"\t out_entries = 0x%016" PRIx64 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(out_todo_list), number_of_entries,
|
||||
reinterpret_cast<uint64_t>(out_entries));
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (out_entries == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (number_of_entries != 0 && out_todo_list == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
*out_entries = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoSetToDoList(int handle, const PlayGoToDo* todo_list,
|
||||
uint32_t number_of_entries) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t todo_list = 0x%016" PRIx64 "\n"
|
||||
"\t number_of_entries = %" PRIu32 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(todo_list), number_of_entries);
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (todo_list == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (number_of_entries == 0) {
|
||||
return PLAYGO_ERROR_BAD_SIZE;
|
||||
}
|
||||
for (uint32_t i = 0; i < number_of_entries; i++) {
|
||||
if (!is_valid_chunk(todo_list[i].chunk_id)) {
|
||||
return PLAYGO_ERROR_BAD_CHUNK_ID;
|
||||
}
|
||||
if (!is_valid_locus(todo_list[i].locus)) {
|
||||
return PLAYGO_ERROR_BAD_LOCUS;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoPrefetch(int handle, const uint16_t* chunk_ids, uint32_t number_of_entries,
|
||||
int8_t minimum_locus) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t chunk_ids = 0x%016" PRIx64 "\n"
|
||||
"\t number_of_entries = %" PRIu32 "\n"
|
||||
"\t minimum_locus = %" PRId8 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(chunk_ids), number_of_entries, minimum_locus);
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (chunk_ids == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (number_of_entries == 0) {
|
||||
return PLAYGO_ERROR_BAD_SIZE;
|
||||
}
|
||||
if (!is_valid_locus(minimum_locus)) {
|
||||
return PLAYGO_ERROR_BAD_LOCUS;
|
||||
}
|
||||
for (uint32_t i = 0; i < number_of_entries; i++) {
|
||||
if (!is_valid_chunk(chunk_ids[i])) {
|
||||
return PLAYGO_ERROR_BAD_CHUNK_ID;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetEta(int handle, const uint16_t* chunk_ids, uint32_t number_of_entries,
|
||||
int64_t* out_eta) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (chunk_ids == nullptr || out_eta == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (number_of_entries == 0) {
|
||||
return PLAYGO_ERROR_BAD_SIZE;
|
||||
}
|
||||
for (uint32_t i = 0; i < number_of_entries; i++) {
|
||||
if (!is_valid_chunk(chunk_ids[i])) {
|
||||
return PLAYGO_ERROR_BAD_CHUNK_ID;
|
||||
}
|
||||
}
|
||||
*out_eta = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetLanguageMask(int handle, uint64_t* out_language_mask) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (out_language_mask == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
|
||||
*out_language_mask = PLAYGO_LANGUAGE_MASK_ALL;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetProgress(int handle, const uint16_t* chunk_ids,
|
||||
uint32_t number_of_entries, PlayGoProgress* out_progress) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (chunk_ids == nullptr || out_progress == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (number_of_entries == 0) {
|
||||
return PLAYGO_ERROR_BAD_SIZE;
|
||||
}
|
||||
for (uint32_t i = 0; i < number_of_entries; i++) {
|
||||
if (!is_valid_chunk(chunk_ids[i])) {
|
||||
return PLAYGO_ERROR_BAD_CHUNK_ID;
|
||||
}
|
||||
}
|
||||
|
||||
out_progress->total_size = number_of_entries;
|
||||
out_progress->progress_size = number_of_entries;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetOptionalChunk(int handle, int32_t type, PlayGoOptionalChunk* option) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (option == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (auto ret = validate_optional_type(type); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
set_optional_chunk(type, option);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoPrefetchOptionalChunk(int handle, int32_t type,
|
||||
const PlayGoOptionalChunk* option) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (auto ret = validate_handle(handle); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
if (option == nullptr) {
|
||||
return PLAYGO_ERROR_BAD_POINTER;
|
||||
}
|
||||
if (auto ret = validate_optional_type(type); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetInstallChunkId(int handle, uint16_t* out_chunk_id_list,
|
||||
uint32_t number_of_entries, uint32_t* out_entries) {
|
||||
PRINT_NAME();
|
||||
|
||||
return PlayGoGetChunkId(handle, out_chunk_id_list, number_of_entries, out_entries);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoGetSupportedOptionalChunk(int handle, int32_t type,
|
||||
PlayGoOptionalChunk* option) {
|
||||
PRINT_NAME();
|
||||
|
||||
return PlayGoGetOptionalChunk(handle, type, option);
|
||||
}
|
||||
|
||||
} // namespace PlayGo
|
||||
|
||||
LIB_DEFINE(InitPlayGo_1) {
|
||||
LIB_FUNC("ts6GlZOKRrE", PlayGo::PlayGoInitialize);
|
||||
LIB_FUNC("MPe0EeBGM-E", PlayGo::PlayGoTerminate);
|
||||
LIB_FUNC("M1Gma1ocrGE", PlayGo::PlayGoOpen);
|
||||
LIB_FUNC("Uco1I0dlDi8", PlayGo::PlayGoClose);
|
||||
LIB_FUNC("uWIYLFkkwqk", PlayGo::PlayGoGetLocus);
|
||||
LIB_FUNC("rvBSfTimejE", PlayGo::PlayGoGetInstallSpeed);
|
||||
LIB_FUNC("4AAcTU9R3XM", PlayGo::PlayGoSetInstallSpeed);
|
||||
LIB_FUNC("73fF1MFU8hA", PlayGo::PlayGoGetChunkId);
|
||||
LIB_FUNC("Nn7zKwnA5q0", PlayGo::PlayGoGetToDoList);
|
||||
LIB_FUNC("gUPGiOQ1tmQ", PlayGo::PlayGoSetToDoList);
|
||||
LIB_FUNC("-Q1-u1a7p0g", PlayGo::PlayGoPrefetch);
|
||||
LIB_FUNC("v6EZ-YWRdMs", PlayGo::PlayGoGetEta);
|
||||
LIB_FUNC("3OMbYZBaa50", PlayGo::PlayGoGetLanguageMask);
|
||||
LIB_FUNC("-RJWNMK3fC8", PlayGo::PlayGoGetProgress);
|
||||
LIB_FUNC("g4AZyxpSAlA", PlayGo::PlayGoGetOptionalChunk);
|
||||
LIB_FUNC("HVAa744ecdw", PlayGo::PlayGoPrefetchOptionalChunk);
|
||||
LIB_FUNC("8-e7E989rCU", PlayGo::PlayGoGetInstallChunkId);
|
||||
LIB_FUNC("IfiN+-oeVWI", PlayGo::PlayGoGetSupportedOptionalChunk);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,381 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
#include "stb_image.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("PngDec", 1, "PngDec", 1, 1);
|
||||
|
||||
namespace PngDec {
|
||||
|
||||
constexpr int32_t PNG_DEC_ERROR_INVALID_ADDR = -2140602367; // 0x80690001
|
||||
constexpr int32_t PNG_DEC_ERROR_INVALID_SIZE = -2140602366; // 0x80690002
|
||||
constexpr int32_t PNG_DEC_ERROR_INVALID_PARAM = -2140602365; // 0x80690003
|
||||
constexpr int32_t PNG_DEC_ERROR_INVALID_HANDLE = -2140602364; // 0x80690004
|
||||
constexpr int32_t PNG_DEC_ERROR_INVALID_WORK_MEMORY = -2140602363; // 0x80690005
|
||||
constexpr int32_t PNG_DEC_ERROR_INVALID_DATA = -2140602352; // 0x80690010
|
||||
constexpr int32_t PNG_DEC_ERROR_DECODE_ERROR = -2140602350; // 0x80690012
|
||||
|
||||
constexpr uint32_t PNG_DEC_ATTRIBUTE_BIT_DEPTH_16 = 1;
|
||||
constexpr uint16_t PNG_DEC_COLOR_SPACE_GRAYSCALE = 2;
|
||||
constexpr uint16_t PNG_DEC_COLOR_SPACE_RGB = 3;
|
||||
constexpr uint16_t PNG_DEC_COLOR_SPACE_CLUT = 4;
|
||||
constexpr uint16_t PNG_DEC_COLOR_SPACE_GRAYSCALE_ALPHA = 18;
|
||||
constexpr uint16_t PNG_DEC_COLOR_SPACE_RGBA = 19;
|
||||
constexpr uint16_t PNG_DEC_PIXEL_FORMAT_R8G8B8A8 = 0;
|
||||
constexpr uint16_t PNG_DEC_PIXEL_FORMAT_B8G8R8A8 = 1;
|
||||
constexpr uint32_t PNG_DEC_IMAGE_FLAG_ADAM7_INTERLACE = 1;
|
||||
constexpr uint32_t PNG_DEC_IMAGE_FLAG_TRNS_CHUNK_EXIST = 2;
|
||||
|
||||
struct PngDecCreateParam {
|
||||
uint32_t this_size;
|
||||
uint32_t attribute;
|
||||
uint32_t max_image_width;
|
||||
};
|
||||
|
||||
struct PngDecDecodeParam {
|
||||
const void* png_mem_addr;
|
||||
void* image_mem_addr;
|
||||
uint32_t png_mem_size;
|
||||
uint32_t image_mem_size;
|
||||
uint16_t pixel_format;
|
||||
uint16_t alpha_value;
|
||||
uint32_t image_pitch;
|
||||
};
|
||||
|
||||
struct PngDecParseParam {
|
||||
const void* png_mem_addr;
|
||||
uint32_t png_mem_size;
|
||||
uint32_t reserved0;
|
||||
};
|
||||
|
||||
struct PngDecImageInfo {
|
||||
uint32_t image_width;
|
||||
uint32_t image_height;
|
||||
uint16_t color_space;
|
||||
uint16_t bit_depth;
|
||||
uint32_t image_flag;
|
||||
};
|
||||
|
||||
struct PngDecContext {
|
||||
uint64_t magic;
|
||||
};
|
||||
|
||||
struct PngHeaderInfo {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint16_t color_space;
|
||||
uint16_t bit_depth;
|
||||
uint32_t image_flag;
|
||||
};
|
||||
|
||||
constexpr uint64_t PNG_DEC_CONTEXT_MAGIC = 0x4b595459504e4744ull; // KYTYPNGD
|
||||
|
||||
static uint32_t ReadBe32(const uint8_t* ptr) {
|
||||
return (static_cast<uint32_t>(ptr[0]) << 24u) | (static_cast<uint32_t>(ptr[1]) << 16u) |
|
||||
(static_cast<uint32_t>(ptr[2]) << 8u) | static_cast<uint32_t>(ptr[3]);
|
||||
}
|
||||
|
||||
static bool AddOverflow(uint32_t a, uint32_t b, uint32_t* out) {
|
||||
*out = a + b;
|
||||
return *out < a;
|
||||
}
|
||||
|
||||
static bool ParsePngHeader(const void* data, uint32_t size, PngHeaderInfo* info) {
|
||||
if (data == nullptr || info == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto* bytes = static_cast<const uint8_t*>(data);
|
||||
constexpr uint8_t png_signature[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
|
||||
|
||||
if (size < 33u || std::memcmp(bytes, png_signature, sizeof(png_signature)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReadBe32(bytes + 8u) != 13u || std::memcmp(bytes + 12u, "IHDR", 4u) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto color_type = bytes[25u];
|
||||
|
||||
switch (color_type) {
|
||||
case 0: info->color_space = PNG_DEC_COLOR_SPACE_GRAYSCALE; break;
|
||||
case 2: info->color_space = PNG_DEC_COLOR_SPACE_RGB; break;
|
||||
case 3: info->color_space = PNG_DEC_COLOR_SPACE_CLUT; break;
|
||||
case 4: info->color_space = PNG_DEC_COLOR_SPACE_GRAYSCALE_ALPHA; break;
|
||||
case 6: info->color_space = PNG_DEC_COLOR_SPACE_RGBA; break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
info->width = ReadBe32(bytes + 16u);
|
||||
info->height = ReadBe32(bytes + 20u);
|
||||
info->bit_depth = bytes[24u];
|
||||
info->image_flag = (bytes[28u] == 1u ? PNG_DEC_IMAGE_FLAG_ADAM7_INTERLACE : 0u);
|
||||
|
||||
if (info->width == 0 || info->height == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t offset = 33u;
|
||||
while (offset + 12u <= size) {
|
||||
const uint32_t length = ReadBe32(bytes + offset);
|
||||
const auto* type = bytes + offset + 4u;
|
||||
|
||||
uint32_t chunk_end = 0;
|
||||
if (AddOverflow(offset, 12u, &chunk_end) || AddOverflow(chunk_end, length, &chunk_end) ||
|
||||
chunk_end > size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::memcmp(type, "tRNS", 4u) == 0) {
|
||||
info->image_flag |= PNG_DEC_IMAGE_FLAG_TRNS_CHUNK_EXIST;
|
||||
}
|
||||
|
||||
if (std::memcmp(type, "IDAT", 4u) == 0 || std::memcmp(type, "IEND", 4u) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
offset = chunk_end;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void FillImageInfo(const PngHeaderInfo& header, PngDecImageInfo* image_info) {
|
||||
if (image_info != nullptr) {
|
||||
image_info->image_width = header.width;
|
||||
image_info->image_height = header.height;
|
||||
image_info->color_space = header.color_space;
|
||||
image_info->bit_depth = header.bit_depth;
|
||||
image_info->image_flag = header.image_flag;
|
||||
}
|
||||
}
|
||||
|
||||
static bool PngHasSourceAlpha(const PngHeaderInfo& header) {
|
||||
return header.color_space == PNG_DEC_COLOR_SPACE_RGBA ||
|
||||
header.color_space == PNG_DEC_COLOR_SPACE_GRAYSCALE_ALPHA ||
|
||||
(header.image_flag & PNG_DEC_IMAGE_FLAG_TRNS_CHUNK_EXIST) != 0;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI PngDecQueryMemorySize(const PngDecCreateParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (param == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
LOGF("\t this_size = %" PRIu32 "\n", param->this_size);
|
||||
LOGF("\t attribute = %" PRIu32 "\n", param->attribute);
|
||||
LOGF("\t max_image_width = %" PRIu32 "\n", param->max_image_width);
|
||||
|
||||
if (param->attribute > PNG_DEC_ATTRIBUTE_BIT_DEPTH_16) {
|
||||
return PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (param->max_image_width == 0) {
|
||||
return PNG_DEC_ERROR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
return sizeof(PngDecContext);
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI PngDecCreate(const PngDecCreateParam* param, void* memory_address,
|
||||
uint32_t memory_size, void** handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (param == nullptr || handle == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
LOGF("\t memory_address = %p\n", memory_address);
|
||||
LOGF("\t memory_size = %" PRIu32 "\n", memory_size);
|
||||
|
||||
if (param->attribute > PNG_DEC_ATTRIBUTE_BIT_DEPTH_16) {
|
||||
return PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (param->max_image_width == 0) {
|
||||
return PNG_DEC_ERROR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (memory_address == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
if (memory_size < sizeof(PngDecContext)) {
|
||||
return PNG_DEC_ERROR_INVALID_WORK_MEMORY;
|
||||
}
|
||||
|
||||
auto* ctx = static_cast<PngDecContext*>(memory_address);
|
||||
ctx->magic = PNG_DEC_CONTEXT_MAGIC;
|
||||
*handle = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI PngDecDecode(void* handle, const PngDecDecodeParam* param,
|
||||
PngDecImageInfo* image_info) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
const auto* ctx = static_cast<const PngDecContext*>(handle);
|
||||
if (ctx->magic != PNG_DEC_CONTEXT_MAGIC) {
|
||||
return PNG_DEC_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (param == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (param->png_mem_addr == nullptr || param->image_mem_addr == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
if (param->pixel_format != PNG_DEC_PIXEL_FORMAT_R8G8B8A8 &&
|
||||
param->pixel_format != PNG_DEC_PIXEL_FORMAT_B8G8R8A8) {
|
||||
return PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
PngHeaderInfo header {};
|
||||
if (!ParsePngHeader(param->png_mem_addr, param->png_mem_size, &header)) {
|
||||
return PNG_DEC_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
FillImageInfo(header, image_info);
|
||||
|
||||
const uint32_t min_pitch = header.width * 4u;
|
||||
const uint32_t pitch = (param->image_pitch == 0 ? min_pitch : param->image_pitch);
|
||||
const uint64_t min_size = static_cast<uint64_t>(pitch) * (header.height - 1u) + min_pitch;
|
||||
|
||||
if (pitch < min_pitch || min_size > param->image_mem_size) {
|
||||
return PNG_DEC_ERROR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
LOGF("\t png_mem_addr = %p\n", param->png_mem_addr);
|
||||
LOGF("\t image_mem_addr = %p\n", param->image_mem_addr);
|
||||
LOGF("\t png_mem_size = %" PRIu32 "\n", param->png_mem_size);
|
||||
LOGF("\t image_mem_size = %" PRIu32 "\n", param->image_mem_size);
|
||||
LOGF("\t pixel_format = %" PRIu16 "\n", param->pixel_format);
|
||||
LOGF("\t alpha_value = %" PRIu16 "\n", param->alpha_value);
|
||||
LOGF("\t image_pitch = %" PRIu32 "\n", param->image_pitch);
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int components = 0;
|
||||
auto* rgba = stbi_load_from_memory(static_cast<const stbi_uc*>(param->png_mem_addr),
|
||||
static_cast<int>(param->png_mem_size), &width, &height,
|
||||
&components, 4);
|
||||
|
||||
if (rgba == nullptr || width <= 0 || height <= 0 ||
|
||||
static_cast<uint32_t>(width) != header.width ||
|
||||
static_cast<uint32_t>(height) != header.height) {
|
||||
if (rgba != nullptr) {
|
||||
stbi_image_free(rgba);
|
||||
}
|
||||
return PNG_DEC_ERROR_DECODE_ERROR;
|
||||
}
|
||||
|
||||
const bool apply_alpha_value = !PngHasSourceAlpha(header);
|
||||
auto* dst_row = static_cast<uint8_t*>(param->image_mem_addr);
|
||||
|
||||
for (uint32_t y = 0; y < header.height; y++) {
|
||||
const auto* src = rgba + static_cast<size_t>(y) * min_pitch;
|
||||
auto* dst = dst_row;
|
||||
|
||||
for (uint32_t x = 0; x < header.width; x++) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = (apply_alpha_value
|
||||
? static_cast<uint8_t>(std::min<uint16_t>(param->alpha_value, 255u))
|
||||
: src[3]);
|
||||
|
||||
if (param->pixel_format == PNG_DEC_PIXEL_FORMAT_B8G8R8A8) {
|
||||
std::swap(dst[0], dst[2]);
|
||||
}
|
||||
|
||||
src += 4;
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
dst_row += pitch;
|
||||
}
|
||||
|
||||
stbi_image_free(rgba);
|
||||
|
||||
return (header.width > 32767u || header.height > 32767u
|
||||
? 0
|
||||
: static_cast<int32_t>((header.width << 16u) | header.height));
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI PngDecDelete(void* handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
auto* ctx = static_cast<PngDecContext*>(handle);
|
||||
if (ctx->magic != PNG_DEC_CONTEXT_MAGIC) {
|
||||
return PNG_DEC_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
ctx->magic = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI PngDecParseHeader(const PngDecParseParam* param,
|
||||
PngDecImageInfo* image_info) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (param == nullptr || image_info == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (param->png_mem_addr == nullptr) {
|
||||
return PNG_DEC_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
if (param->reserved0 != 0) {
|
||||
return PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
PngHeaderInfo header {};
|
||||
if (!ParsePngHeader(param->png_mem_addr, param->png_mem_size, &header)) {
|
||||
return PNG_DEC_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
FillImageInfo(header, image_info);
|
||||
|
||||
LOGF("\t image_width = %" PRIu32 "\n", image_info->image_width);
|
||||
LOGF("\t image_height = %" PRIu32 "\n", image_info->image_height);
|
||||
LOGF("\t color_space = %" PRIu16 "\n", image_info->color_space);
|
||||
LOGF("\t bit_depth = %" PRIu16 "\n", image_info->bit_depth);
|
||||
LOGF("\t image_flag = 0x%08" PRIx32 "\n", image_info->image_flag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace PngDec
|
||||
|
||||
LIB_DEFINE(InitPngDec_1) {
|
||||
PRINT_NAME_ENABLE(true);
|
||||
|
||||
LIB_FUNC("-6srIGbLTIU", PngDec::PngDecQueryMemorySize);
|
||||
LIB_FUNC("m0uW+8pFyaw", PngDec::PngDecCreate);
|
||||
LIB_FUNC("WC216DD3El4", PngDec::PngDecDecode);
|
||||
LIB_FUNC("QbD+eENEwo8", PngDec::PngDecDelete);
|
||||
LIB_FUNC("U6h4e5JRPaQ", PngDec::PngDecParseHeader);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,353 @@
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibPsml {
|
||||
|
||||
LIB_VERSION("Psml", 1, "Psml", 1, 1);
|
||||
|
||||
namespace Psml {
|
||||
|
||||
constexpr int Error(uint32_t value) {
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
|
||||
constexpr int PSML_ERROR_NOT_INITIALIZED = Error(0x8a810001u);
|
||||
constexpr int PSML_ERROR_INVALID_OBJECT = Error(0x8a810005u);
|
||||
constexpr int PSML_ERROR_INVALID_POINTER = Error(0x8a810009u);
|
||||
constexpr int PSML_ERROR_INVALID_VALUE = Error(0x8a81000du);
|
||||
constexpr int PSML_ERROR_NULL_OBJECT = Error(0x8a810014u);
|
||||
|
||||
constexpr uint32_t SHARED_RESOURCES_MAGIC = 0xa9c4;
|
||||
constexpr uint32_t CONTEXT_MAGIC = 0x9231;
|
||||
|
||||
constexpr uint64_t MAIN_MEMORY_BLOCK_SIZE = 0x200000;
|
||||
constexpr uint64_t MAIN_MEMORY_ALIGNMENT = 0x200000;
|
||||
constexpr uint64_t EXTRA_VA_BYTES = 0x600000;
|
||||
|
||||
struct MainMemoryRequirements {
|
||||
uint64_t block_size;
|
||||
uint64_t alignment;
|
||||
uint64_t block_count;
|
||||
};
|
||||
|
||||
struct MainMemoryParameters {
|
||||
uint32_t type;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
struct DirectMemoryBlock {
|
||||
uint64_t address;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
struct SharedResourcesInitParameters {
|
||||
uint32_t type;
|
||||
uint32_t reserved;
|
||||
const DirectMemoryBlock* blocks;
|
||||
uint64_t block_count;
|
||||
uint64_t virtual_address_start;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MainMemoryRequirements) == 24);
|
||||
static_assert(sizeof(DirectMemoryBlock) == 16);
|
||||
|
||||
static bool g_initialized = false;
|
||||
static uint32_t g_supported_modes = 0x3;
|
||||
static std::atomic<int32_t> g_shared_ref_count = 0;
|
||||
|
||||
static uint64_t BaseVaBytes(uint32_t type) {
|
||||
// The native implementation indexes this table before adding one 6 MiB range.
|
||||
switch (type) {
|
||||
case 0: return 0x06200000;
|
||||
case 1: return 0x18200000;
|
||||
case 2: return 0x12200000;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSupportedType(uint32_t type) {
|
||||
switch (type) {
|
||||
case 0: return true;
|
||||
case 1: return (g_supported_modes & 0x1u) != 0;
|
||||
case 2: return (g_supported_modes & 0x2u) != 0;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t RequiredBlockCount(uint32_t type) {
|
||||
const auto base = BaseVaBytes(type);
|
||||
if (base == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (base + EXTRA_VA_BYTES) / MAIN_MEMORY_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static int CheckInitialized() {
|
||||
return (g_initialized ? OK : PSML_ERROR_NOT_INITIALIZED);
|
||||
}
|
||||
|
||||
static void MarkSharedResources(void* resources, const SharedResourcesInitParameters& params) {
|
||||
auto* bytes = static_cast<uint8_t*>(resources);
|
||||
|
||||
*reinterpret_cast<uint32_t*>(bytes) = SHARED_RESOURCES_MAGIC;
|
||||
*reinterpret_cast<const DirectMemoryBlock**>(bytes + 0x08) = params.blocks;
|
||||
*reinterpret_cast<uint64_t*>(bytes + 0x18) = params.block_count;
|
||||
*reinterpret_cast<uint32_t*>(bytes + 0x20) = params.type;
|
||||
*reinterpret_cast<uint64_t*>(bytes + 0x28) = params.virtual_address_start;
|
||||
}
|
||||
|
||||
static bool HasKnownObjectMagic(const void* object) {
|
||||
if (object == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const auto magic = *static_cast<const uint32_t*>(object);
|
||||
return magic == SHARED_RESOURCES_MAGIC || magic == CONTEXT_MAGIC;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlInitialize() {
|
||||
PRINT_NAME();
|
||||
|
||||
g_initialized = true;
|
||||
g_supported_modes = 0x3;
|
||||
g_shared_ref_count = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlGetMainMemoryRequirements(MainMemoryRequirements* out,
|
||||
const MainMemoryParameters* params) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (out == nullptr || params == nullptr) {
|
||||
return PSML_ERROR_INVALID_POINTER;
|
||||
}
|
||||
if (!IsSupportedType(params->type)) {
|
||||
return PSML_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
out->block_size = MAIN_MEMORY_BLOCK_SIZE;
|
||||
out->alignment = MAIN_MEMORY_ALIGNMENT;
|
||||
out->block_count = RequiredBlockCount(params->type);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI
|
||||
PsmlSharedResourcesInitialize(void* resources, const SharedResourcesInitParameters* params) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (resources == nullptr || params == nullptr || params->blocks == nullptr) {
|
||||
return PSML_ERROR_INVALID_POINTER;
|
||||
}
|
||||
if (params->reserved != 0 || !IsSupportedType(params->type) ||
|
||||
params->block_count < RequiredBlockCount(params->type)) {
|
||||
return PSML_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
MarkSharedResources(resources, *params);
|
||||
g_shared_ref_count.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlSharedResourcesFinalize(void* resources) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (resources == nullptr) {
|
||||
return PSML_ERROR_NULL_OBJECT;
|
||||
}
|
||||
|
||||
g_shared_ref_count.fetch_sub(1, std::memory_order_relaxed);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlGetContextMemoryRequirements(MainMemoryRequirements* out,
|
||||
uint64_t /*params*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (out == nullptr) {
|
||||
return PSML_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
out->block_size = MAIN_MEMORY_BLOCK_SIZE;
|
||||
out->alignment = MAIN_MEMORY_ALIGNMENT;
|
||||
out->block_count = 1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlContextInitialize(void* context, const void* params) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (context == nullptr || params == nullptr) {
|
||||
return PSML_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
auto* bytes = static_cast<uint8_t*>(context);
|
||||
auto* params_bytes = static_cast<const uint8_t*>(params);
|
||||
auto* shared_resources = *reinterpret_cast<void* const*>(params_bytes + 0x08);
|
||||
if (shared_resources == nullptr) {
|
||||
return PSML_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
*reinterpret_cast<uint32_t*>(bytes) = CONTEXT_MAGIC;
|
||||
*reinterpret_cast<void**>(bytes + 0x360) = shared_resources;
|
||||
*reinterpret_cast<uint8_t*>(bytes + 0x368) = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlContextFinalize(void* context) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (!HasKnownObjectMagic(context)) {
|
||||
return PSML_ERROR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
*static_cast<uint32_t*>(context) = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlGetWorkAreaSize(const void* object, uint32_t* out_size) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (!HasKnownObjectMagic(object)) {
|
||||
return PSML_ERROR_INVALID_OBJECT;
|
||||
}
|
||||
if (out_size == nullptr) {
|
||||
return PSML_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
*out_size = 0x600;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlDispatch(void* context, uint64_t command, uint64_t params) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (!HasKnownObjectMagic(context)) {
|
||||
return PSML_ERROR_INVALID_OBJECT;
|
||||
}
|
||||
if (command == 0 || params == 0) {
|
||||
return PSML_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlGetProgress(const void* object, float* out_progress,
|
||||
uint32_t /*frame_index*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (!HasKnownObjectMagic(object)) {
|
||||
return PSML_ERROR_INVALID_OBJECT;
|
||||
}
|
||||
if (out_progress == nullptr) {
|
||||
return PSML_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
*out_progress = 0.0f;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlRequestCapture(const void* object) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (!HasKnownObjectMagic(object)) {
|
||||
return PSML_ERROR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PsmlValidateObject(const void* object) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto init_error = CheckInitialized();
|
||||
if (init_error != OK) {
|
||||
return init_error;
|
||||
}
|
||||
if (!HasKnownObjectMagic(object)) {
|
||||
return PSML_ERROR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace Psml
|
||||
|
||||
LIB_DEFINE(InitPsml_1) {
|
||||
LIB_FUNC("3WVD91e12ZQ", Psml::PsmlInitialize);
|
||||
LIB_FUNC("+2KpvixvL6E", Psml::PsmlGetMainMemoryRequirements);
|
||||
LIB_FUNC("eWoKNeB6V-k", Psml::PsmlSharedResourcesInitialize);
|
||||
LIB_FUNC("jEevBXmagOQ", Psml::PsmlSharedResourcesFinalize);
|
||||
LIB_FUNC("EO9YQXmJEN8", Psml::PsmlGetContextMemoryRequirements);
|
||||
LIB_FUNC("IMlj247LdTo", Psml::PsmlGetContextMemoryRequirements);
|
||||
LIB_FUNC("sjTyYheKTrU", Psml::PsmlGetContextMemoryRequirements);
|
||||
LIB_FUNC("ArakEpzsZo0", Psml::PsmlGetContextMemoryRequirements);
|
||||
LIB_FUNC("VGjrQa-WqdU", Psml::PsmlGetContextMemoryRequirements);
|
||||
LIB_FUNC("2ecEbQaf9VU", Psml::PsmlContextInitialize);
|
||||
LIB_FUNC("vUk2pWMx3KQ", Psml::PsmlContextInitialize);
|
||||
LIB_FUNC("gxv3i+MTEzU", Psml::PsmlContextInitialize);
|
||||
LIB_FUNC("JaLBe0P3jSU", Psml::PsmlContextFinalize);
|
||||
LIB_FUNC("AHalTX9wFZY", Psml::PsmlGetWorkAreaSize);
|
||||
LIB_FUNC("RUNLFro+qok", Psml::PsmlDispatch);
|
||||
LIB_FUNC("GHna9-DvnUk", Psml::PsmlGetProgress);
|
||||
LIB_FUNC("GJY0MvuTcs8", Psml::PsmlRequestCapture);
|
||||
LIB_FUNC("LXq+6mIxpCw", Psml::PsmlValidateObject);
|
||||
LIB_FUNC("FSGaTQze0UY", Psml::PsmlValidateObject);
|
||||
}
|
||||
|
||||
} // namespace LibPsml
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,594 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/dateTime.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibRtc {
|
||||
|
||||
LIB_VERSION("Rtc", 1, "Rtc", 1, 1);
|
||||
|
||||
namespace Rtc {
|
||||
|
||||
constexpr int RTC_ERROR_DATETIME_UNINITIALIZED = 0x7ffef9fe;
|
||||
constexpr int RTC_ERROR_INVALID_POINTER = -2135621630; /* 0x80B50002 */
|
||||
constexpr int RTC_ERROR_INVALID_VALUE = -2135621629; /* 0x80B50003 */
|
||||
constexpr int RTC_ERROR_INVALID_YEAR = -2135621624; /* 0x80B50008 */
|
||||
constexpr int RTC_ERROR_INVALID_MONTH = -2135621623; /* 0x80B50009 */
|
||||
constexpr int RTC_ERROR_INVALID_DAY = -2135621622; /* 0x80B5000A */
|
||||
constexpr int RTC_ERROR_INVALID_HOUR = -2135621621; /* 0x80B5000B */
|
||||
constexpr int RTC_ERROR_INVALID_MINUTE = -2135621620; /* 0x80B5000C */
|
||||
constexpr int RTC_ERROR_INVALID_SECOND = -2135621619; /* 0x80B5000D */
|
||||
constexpr int RTC_ERROR_INVALID_MICROSECOND = -2135621618; /* 0x80B5000E */
|
||||
|
||||
constexpr uint64_t RTC_UNIX_EPOCH_TICKS = 0xdcbffeff2bc000ull;
|
||||
constexpr uint64_t RTC_WIN32_FILETIME_EPOCH_TICKS = 0xb36168b6a58000ull;
|
||||
|
||||
struct RtcDateTime {
|
||||
uint16_t year;
|
||||
uint16_t month;
|
||||
uint16_t day;
|
||||
uint16_t hour;
|
||||
uint16_t minute;
|
||||
uint16_t second;
|
||||
uint32_t microsecond;
|
||||
};
|
||||
|
||||
static_assert(sizeof(RtcDateTime) == 16);
|
||||
|
||||
struct RtcTick {
|
||||
uint64_t tick;
|
||||
};
|
||||
|
||||
static_assert(sizeof(RtcTick) == 8);
|
||||
|
||||
static int KYTY_SYSV_ABI RtcCheckValid(const RtcDateTime* time) {
|
||||
if (time == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
if (time->year == 0 || time->year > 9999) {
|
||||
return RTC_ERROR_INVALID_YEAR;
|
||||
}
|
||||
if (time->month == 0 || time->month > 12) {
|
||||
return RTC_ERROR_INVALID_MONTH;
|
||||
}
|
||||
if (time->day == 0 || !Common::Date::IsValid(time->year, time->month, time->day)) {
|
||||
return RTC_ERROR_INVALID_DAY;
|
||||
}
|
||||
if (time->hour >= 24) {
|
||||
return RTC_ERROR_INVALID_HOUR;
|
||||
}
|
||||
if (time->minute >= 60) {
|
||||
return RTC_ERROR_INVALID_MINUTE;
|
||||
}
|
||||
if (time->second >= 60) {
|
||||
return RTC_ERROR_INVALID_SECOND;
|
||||
}
|
||||
if (time->microsecond >= 1000000) {
|
||||
return RTC_ERROR_INVALID_MICROSECOND;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int RtcGetDaysInMonth(int year, int month) {
|
||||
if (year <= 0 || year > 9999) {
|
||||
return RTC_ERROR_INVALID_YEAR;
|
||||
}
|
||||
if (month <= 0 || month > 12) {
|
||||
return RTC_ERROR_INVALID_MONTH;
|
||||
}
|
||||
|
||||
if (month == 2 && Common::Date::IsLeapYear(year)) {
|
||||
return 29;
|
||||
}
|
||||
|
||||
return Common::Date::DaysInMonth(month);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcIsLeapYear(int year) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (year <= 0 || year > 9999) {
|
||||
return RTC_ERROR_INVALID_YEAR;
|
||||
}
|
||||
|
||||
return Common::Date::IsLeapYear(year) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetDayOfWeek(int year, int month, int day) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto days = RtcGetDaysInMonth(year, month);
|
||||
if (days < 0) {
|
||||
return days;
|
||||
}
|
||||
if (day <= 0 || day > days) {
|
||||
return RTC_ERROR_INVALID_DAY;
|
||||
}
|
||||
|
||||
const auto dow = Common::Date(year, month, day).DayOfWeek();
|
||||
return (dow == 7 ? 0 : dow);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetDaysInMonthExport(int year, int month) {
|
||||
PRINT_NAME();
|
||||
|
||||
return RtcGetDaysInMonth(year, month);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetTickResolution() {
|
||||
PRINT_NAME();
|
||||
|
||||
return 1000000;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetCurrentClockLocalTime(RtcDateTime* time) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (time == nullptr) {
|
||||
return RTC_ERROR_DATETIME_UNINITIALIZED;
|
||||
}
|
||||
|
||||
const auto now = Common::DateTime::FromSystem();
|
||||
const auto date = now.GetDate();
|
||||
const auto tod = now.GetTime();
|
||||
|
||||
time->year = static_cast<uint16_t>(date.Year());
|
||||
time->month = static_cast<uint16_t>(date.Month());
|
||||
time->day = static_cast<uint16_t>(date.Day());
|
||||
time->hour = static_cast<uint16_t>(tod.Hour24());
|
||||
time->minute = static_cast<uint16_t>(tod.Minute());
|
||||
time->second = static_cast<uint16_t>(tod.Second());
|
||||
time->microsecond = static_cast<uint32_t>(tod.Msec() * 1000);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcSetTick(RtcDateTime* time, const RtcTick* tick) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (time == nullptr || tick == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
auto days = tick->tick / 86400000000ull;
|
||||
auto usec = tick->tick % 86400000000ull;
|
||||
|
||||
days += 307;
|
||||
|
||||
auto j = (days << 2) - 1;
|
||||
auto ly = j / 146097;
|
||||
|
||||
j -= 146097 * ly;
|
||||
auto ld = j >> 2;
|
||||
|
||||
j = ((ld << 2) + 3) / 1461;
|
||||
ld = (((ld << 2) + 7) - 1461 * j) >> 2;
|
||||
|
||||
auto lm = (5 * ld - 3) / 153;
|
||||
ld = (5 * ld + 2 - 153 * lm) / 5;
|
||||
ly = 100 * ly + j;
|
||||
|
||||
if (lm < 10) {
|
||||
lm += 3;
|
||||
} else {
|
||||
lm -= 9;
|
||||
ly++;
|
||||
}
|
||||
|
||||
if (ly == 0 || ly > 9999) {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
time->year = static_cast<uint16_t>(ly);
|
||||
time->month = static_cast<uint16_t>(lm);
|
||||
time->day = static_cast<uint16_t>(ld);
|
||||
|
||||
time->hour = static_cast<uint16_t>(usec / 3600000000ull);
|
||||
usec %= 3600000000ull;
|
||||
time->minute = static_cast<uint16_t>(usec / 60000000ull);
|
||||
usec %= 60000000ull;
|
||||
time->second = static_cast<uint16_t>(usec / 1000000ull);
|
||||
usec %= 1000000ull;
|
||||
time->microsecond = static_cast<uint32_t>(usec);
|
||||
|
||||
return RtcCheckValid(time);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetTick(const RtcDateTime* time, RtcTick* tick) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (time == nullptr || tick == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
const auto valid = RtcCheckValid(time);
|
||||
if (valid != OK) {
|
||||
return valid;
|
||||
}
|
||||
|
||||
uint64_t year = time->year;
|
||||
uint64_t month = time->month;
|
||||
|
||||
if (month > 2) {
|
||||
month -= 3;
|
||||
} else {
|
||||
month += 9;
|
||||
year -= 1;
|
||||
}
|
||||
|
||||
const auto c = year / 100;
|
||||
const auto ya = year - 100 * c;
|
||||
|
||||
auto days = ((146097 * c) >> 2) + ((1461 * ya) >> 2) + (153 * month + 2) / 5 + time->day;
|
||||
days -= 307;
|
||||
days *= 86400000000ull;
|
||||
|
||||
const auto usec = static_cast<uint64_t>(time->hour) * 3600000000ull +
|
||||
static_cast<uint64_t>(time->minute) * 60000000ull +
|
||||
static_cast<uint64_t>(time->second) * 1000000ull + time->microsecond;
|
||||
|
||||
tick->tick = days + usec;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetCurrentTick(RtcTick* tick) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (tick == nullptr) {
|
||||
return RTC_ERROR_DATETIME_UNINITIALIZED;
|
||||
}
|
||||
|
||||
const auto now = Common::DateTime::FromSystemUTC();
|
||||
const auto date = now.GetDate();
|
||||
const auto tod = now.GetTime();
|
||||
|
||||
RtcDateTime time {};
|
||||
time.year = static_cast<uint16_t>(date.Year());
|
||||
time.month = static_cast<uint16_t>(date.Month());
|
||||
time.day = static_cast<uint16_t>(date.Day());
|
||||
time.hour = static_cast<uint16_t>(tod.Hour24());
|
||||
time.minute = static_cast<uint16_t>(tod.Minute());
|
||||
time.second = static_cast<uint16_t>(tod.Second());
|
||||
time.microsecond = static_cast<uint32_t>(tod.Msec() * 1000);
|
||||
|
||||
return RtcGetTick(&time, tick);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetCurrentNetworkTick(RtcTick* tick) {
|
||||
PRINT_NAME();
|
||||
|
||||
return RtcGetCurrentTick(tick);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetCurrentClock(RtcDateTime* time, int time_zone_minutes) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (time == nullptr) {
|
||||
return RTC_ERROR_DATETIME_UNINITIALIZED;
|
||||
}
|
||||
|
||||
RtcTick tick {};
|
||||
auto ret = RtcGetCurrentTick(&tick);
|
||||
if (ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
tick.tick += static_cast<int64_t>(time_zone_minutes) * 60000000ll;
|
||||
|
||||
return RtcSetTick(time, &tick);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcConvertUtcToLocalTime(const RtcTick* utc, RtcTick* local_time) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (utc == nullptr || local_time == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
// Keep host-independent behavior for now; Kyty stores RTC ticks in UTC.
|
||||
*local_time = *utc;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcConvertLocalTimeToUtc(const RtcTick* local_time, RtcTick* utc) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (local_time == nullptr || utc == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
// Keep host-independent behavior for now; Kyty stores RTC ticks in UTC.
|
||||
*utc = *local_time;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcFormatRFC3339(char* date_time, const RtcTick* utc,
|
||||
int time_zone_minutes) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (date_time == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
RtcTick tick {};
|
||||
if (utc == nullptr) {
|
||||
auto ret = RtcGetCurrentTick(&tick);
|
||||
if (ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
tick = *utc;
|
||||
}
|
||||
|
||||
const auto offset_ticks = static_cast<int64_t>(time_zone_minutes) * 60000000ll;
|
||||
if (offset_ticks < 0 && tick.tick < static_cast<uint64_t>(-offset_ticks)) {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
tick.tick = static_cast<uint64_t>(static_cast<int64_t>(tick.tick) + offset_ticks);
|
||||
|
||||
RtcDateTime time {};
|
||||
auto ret = RtcSetTick(&time, &tick);
|
||||
if (ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
char zone[8] {};
|
||||
if (time_zone_minutes == 0) {
|
||||
std::snprintf(zone, sizeof(zone), "Z");
|
||||
} else {
|
||||
const auto sign = (time_zone_minutes < 0 ? '-' : '+');
|
||||
auto minutes = (time_zone_minutes < 0 ? -time_zone_minutes : time_zone_minutes);
|
||||
std::snprintf(zone, sizeof(zone), "%c%02d:%02d", sign, minutes / 60, minutes % 60);
|
||||
}
|
||||
|
||||
std::snprintf(date_time, 32, "%04u-%02u-%02uT%02u:%02u:%02u.%02u%s",
|
||||
static_cast<unsigned>(time.year), static_cast<unsigned>(time.month),
|
||||
static_cast<unsigned>(time.day), static_cast<unsigned>(time.hour),
|
||||
static_cast<unsigned>(time.minute), static_cast<unsigned>(time.second),
|
||||
static_cast<unsigned>(time.microsecond / 10000), zone);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcParseRFC3339(RtcTick* utc, const char* date_time) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (utc == nullptr || date_time == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
RtcDateTime time {};
|
||||
int parsed = 0;
|
||||
int count = std::sscanf(date_time, "%hu-%hu-%huT%hu:%hu:%hu%n", &time.year, &time.month,
|
||||
&time.day, &time.hour, &time.minute, &time.second, &parsed);
|
||||
if (count != 6) {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
const char* pos = date_time + parsed;
|
||||
if (*pos == '.') {
|
||||
pos++;
|
||||
uint32_t microsecond = 0;
|
||||
int digits = 0;
|
||||
while (*pos >= '0' && *pos <= '9') {
|
||||
if (digits < 6) {
|
||||
microsecond = microsecond * 10 + static_cast<uint32_t>(*pos - '0');
|
||||
}
|
||||
digits++;
|
||||
pos++;
|
||||
}
|
||||
while (digits > 0 && digits < 6) {
|
||||
microsecond *= 10;
|
||||
digits++;
|
||||
}
|
||||
time.microsecond = microsecond;
|
||||
}
|
||||
|
||||
auto ret = RtcGetTick(&time, utc);
|
||||
if (ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (*pos == 'Z' || *pos == '\0') {
|
||||
return OK;
|
||||
}
|
||||
if (*pos != '+' && *pos != '-') {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
int zone_hour = 0;
|
||||
int zone_min = 0;
|
||||
if (std::sscanf(pos + 1, "%02d:%02d", &zone_hour, &zone_min) != 2) {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
int zone_minutes = zone_hour * 60 + zone_min;
|
||||
if (*pos == '-') {
|
||||
zone_minutes = -zone_minutes;
|
||||
}
|
||||
|
||||
const auto offset_ticks = static_cast<int64_t>(zone_minutes) * 60000000ll;
|
||||
if (offset_ticks > 0 && utc->tick < static_cast<uint64_t>(offset_ticks)) {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
utc->tick = static_cast<uint64_t>(static_cast<int64_t>(utc->tick) - offset_ticks);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetTime_t(const RtcDateTime* time, int64_t* seconds) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (time == nullptr || seconds == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
RtcTick tick {};
|
||||
auto ret = RtcGetTick(time, &tick);
|
||||
if (ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*seconds = (tick.tick < RTC_UNIX_EPOCH_TICKS
|
||||
? 0
|
||||
: static_cast<int64_t>((tick.tick - RTC_UNIX_EPOCH_TICKS) / 1000000ull));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcGetWin32FileTime(const RtcDateTime* time, uint64_t* win32_time) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (time == nullptr || win32_time == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
RtcTick tick {};
|
||||
auto ret = RtcGetTick(time, &tick);
|
||||
if (ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*win32_time = (tick.tick < RTC_WIN32_FILETIME_EPOCH_TICKS
|
||||
? 0
|
||||
: (tick.tick - RTC_WIN32_FILETIME_EPOCH_TICKS) * 10ull);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcSetWin32FileTime(RtcDateTime* time, uint64_t win32_time) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (time == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
if (win32_time / 10ull >
|
||||
std::numeric_limits<uint64_t>::max() - RTC_WIN32_FILETIME_EPOCH_TICKS) {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
RtcTick tick {};
|
||||
tick.tick = win32_time / 10ull + RTC_WIN32_FILETIME_EPOCH_TICKS;
|
||||
|
||||
return RtcSetTick(time, &tick);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcSetTime_t(RtcDateTime* time, int64_t seconds) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (time == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
if (seconds < 0) {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
const auto sec = static_cast<uint64_t>(seconds);
|
||||
if (sec > (std::numeric_limits<uint64_t>::max() - RTC_UNIX_EPOCH_TICKS) / 1000000ull) {
|
||||
return RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
RtcTick tick {};
|
||||
tick.tick = sec * 1000000ull + RTC_UNIX_EPOCH_TICKS;
|
||||
|
||||
return RtcSetTick(time, &tick);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcTickAddTicks(RtcTick* dst, const RtcTick* src, int64_t ticks) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (dst == nullptr || src == nullptr) {
|
||||
return RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
dst->tick = src->tick + ticks;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcTickAddMicroseconds(RtcTick* dst, const RtcTick* src, int64_t usec) {
|
||||
PRINT_NAME();
|
||||
|
||||
return RtcTickAddTicks(dst, src, usec);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcTickAddSeconds(RtcTick* dst, const RtcTick* src, int64_t seconds) {
|
||||
PRINT_NAME();
|
||||
|
||||
return RtcTickAddTicks(dst, src, seconds * 1000000ll);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcTickAddMinutes(RtcTick* dst, const RtcTick* src, int64_t minutes) {
|
||||
PRINT_NAME();
|
||||
|
||||
return RtcTickAddTicks(dst, src, minutes * 60000000ll);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcTickAddHours(RtcTick* dst, const RtcTick* src, int32_t hours) {
|
||||
PRINT_NAME();
|
||||
|
||||
return RtcTickAddTicks(dst, src, static_cast<int64_t>(hours) * 3600000000ll);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcTickAddDays(RtcTick* dst, const RtcTick* src, int32_t days) {
|
||||
PRINT_NAME();
|
||||
|
||||
return RtcTickAddTicks(dst, src, static_cast<int64_t>(days) * 86400000000ll);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI RtcTickAddWeeks(RtcTick* dst, const RtcTick* src, int32_t weeks) {
|
||||
PRINT_NAME();
|
||||
|
||||
return RtcTickAddTicks(dst, src, static_cast<int64_t>(weeks) * 604800000000ll);
|
||||
}
|
||||
|
||||
} // namespace Rtc
|
||||
|
||||
LIB_DEFINE(InitRtc_1_Rtc) {
|
||||
LIB_FUNC("lPEBYdVX0XQ", Rtc::RtcCheckValid);
|
||||
LIB_FUNC("8Yr143yEnRo", Rtc::RtcConvertLocalTimeToUtc);
|
||||
LIB_FUNC("M1TvFst-jrM", Rtc::RtcConvertUtcToLocalTime);
|
||||
LIB_FUNC("WJ3rqFwymew", Rtc::RtcFormatRFC3339);
|
||||
LIB_FUNC("8lfvnRMqwEM", Rtc::RtcGetCurrentClock);
|
||||
LIB_FUNC("ZPD1YOKI+Kw", Rtc::RtcGetCurrentClockLocalTime);
|
||||
LIB_FUNC("18B2NS1y9UU", Rtc::RtcGetCurrentTick);
|
||||
LIB_FUNC("zO9UL3qIINQ", Rtc::RtcGetCurrentNetworkTick);
|
||||
LIB_FUNC("CyIK-i4XdgQ", Rtc::RtcGetDayOfWeek);
|
||||
LIB_FUNC("Ug8pCwQvh0c", Rtc::RtcIsLeapYear);
|
||||
LIB_FUNC("3O7Ln8AqJ1o", Rtc::RtcGetDaysInMonthExport);
|
||||
LIB_FUNC("8w-H19ip48I", Rtc::RtcGetTick);
|
||||
LIB_FUNC("jMNwqYr4R-k", Rtc::RtcGetTickResolution);
|
||||
LIB_FUNC("BtqmpTRXHgk", Rtc::RtcGetTime_t);
|
||||
LIB_FUNC("jfRO0uTjtzA", Rtc::RtcGetWin32FileTime);
|
||||
LIB_FUNC("99bMGglFW3I", Rtc::RtcParseRFC3339);
|
||||
LIB_FUNC("n5JiAJXsbcs", Rtc::RtcSetWin32FileTime);
|
||||
LIB_FUNC("ueega6v3GUw", Rtc::RtcSetTick);
|
||||
LIB_FUNC("bDEVVP4bTjQ", Rtc::RtcSetTime_t);
|
||||
LIB_FUNC("NR1J0N7L2xY", Rtc::RtcTickAddDays);
|
||||
LIB_FUNC("MDc5cd8HfCA", Rtc::RtcTickAddHours);
|
||||
LIB_FUNC("XPIiw58C+GM", Rtc::RtcTickAddMicroseconds);
|
||||
LIB_FUNC("mn-tf4QiFzk", Rtc::RtcTickAddMinutes);
|
||||
LIB_FUNC("07O525HgICs", Rtc::RtcTickAddSeconds);
|
||||
LIB_FUNC("AqVMssr52Rc", Rtc::RtcTickAddTicks);
|
||||
LIB_FUNC("gI4t194c2W8", Rtc::RtcTickAddWeeks);
|
||||
}
|
||||
|
||||
} // namespace LibRtc
|
||||
|
||||
LIB_DEFINE(InitRtc_1) {
|
||||
LibRtc::InitRtc_1_Rtc(s);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("Rudp", 1, "Rudp", 1, 1);
|
||||
|
||||
namespace Rudp {
|
||||
|
||||
using RudpEventHandler = void (*)(int ctx_id, int event_id, int error_code, void* arg);
|
||||
|
||||
static RudpEventHandler g_event_handler = nullptr;
|
||||
static void* g_event_arg = nullptr;
|
||||
static bool g_initialized = false;
|
||||
|
||||
static KYTY_SYSV_ABI int RudpInit(void* mem_pool, int mem_pool_size) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t mem_pool = 0x%016" PRIx64 "\n"
|
||||
"\t mem_pool_size = %d\n",
|
||||
reinterpret_cast<uint64_t>(mem_pool), mem_pool_size);
|
||||
|
||||
g_initialized = true;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int RudpEnableInternalIOThread(uint32_t stack_size, uint32_t priority) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t stack_size = %" PRIu32 "\n"
|
||||
"\t priority = %" PRIu32 "\n",
|
||||
stack_size, priority);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int RudpSetEventHandler(RudpEventHandler handler, void* arg) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handler = 0x%016" PRIx64 "\n"
|
||||
"\t arg = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(handler), reinterpret_cast<uint64_t>(arg));
|
||||
|
||||
g_event_handler = handler;
|
||||
g_event_arg = arg;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace Rudp
|
||||
|
||||
LIB_DEFINE(InitRudp_1) {
|
||||
LIB_FUNC("amuBfI-AQc4", Rudp::RudpInit);
|
||||
LIB_FUNC("6PBNpsgyaxw", Rudp::RudpEnableInternalIOThread);
|
||||
LIB_FUNC("SUEVes8gvmw", Rudp::RudpSetEventHandler);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,916 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/file.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "kernel/fileSystem.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
#include "loader/systemContent.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("SaveData", 1, "SaveData", 1, 1);
|
||||
|
||||
namespace SaveData {
|
||||
|
||||
// TODO(): specify dir at launcher
|
||||
static constexpr char SAVE_DATA_DIR[] = "_SaveData";
|
||||
static constexpr char SAVE_DATA_POINT[] = "/savedata0";
|
||||
static constexpr uint64_t SAVE_DATA_BLOCKS_MAX = 16384;
|
||||
|
||||
struct SceSaveDataDirName {
|
||||
char data[32];
|
||||
};
|
||||
|
||||
struct SceSaveDataTitleId {
|
||||
char data[10];
|
||||
char padding[6];
|
||||
};
|
||||
|
||||
struct SceSaveDataFingerprint {
|
||||
char data[65];
|
||||
char padding[15];
|
||||
};
|
||||
|
||||
struct SaveDataParam;
|
||||
|
||||
enum class SaveDataSortKey : uint32_t {
|
||||
DirName = 0,
|
||||
UserParam = 1,
|
||||
Blocks = 2,
|
||||
Mtime = 3,
|
||||
FreeBlocks = 5,
|
||||
};
|
||||
|
||||
enum class SaveDataSortOrder : uint32_t {
|
||||
Ascent = 0,
|
||||
Descent = 1,
|
||||
};
|
||||
|
||||
struct SaveDataDirNameSearchCond {
|
||||
int32_t user_id;
|
||||
int32_t pad;
|
||||
const SceSaveDataTitleId* title_id;
|
||||
const SceSaveDataDirName* dir_name;
|
||||
SaveDataSortKey key;
|
||||
SaveDataSortOrder order;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataSearchInfo {
|
||||
uint64_t blocks;
|
||||
uint64_t free_blocks;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataDirNameSearchResult {
|
||||
uint32_t hit_num;
|
||||
int32_t pad;
|
||||
SceSaveDataDirName* dir_names;
|
||||
uint32_t dir_names_num;
|
||||
uint32_t set_num;
|
||||
SaveDataParam* params;
|
||||
SaveDataSearchInfo* infos;
|
||||
uint8_t reserved[12];
|
||||
int32_t pad2;
|
||||
};
|
||||
|
||||
struct SaveDataMountPoint {
|
||||
char data[16];
|
||||
};
|
||||
|
||||
struct SaveDataMount3 {
|
||||
int user_id;
|
||||
int pad;
|
||||
const SceSaveDataDirName* dir_name;
|
||||
uint64_t blocks;
|
||||
uint64_t system_blocks;
|
||||
uint32_t mount_mode;
|
||||
int pad2;
|
||||
int32_t resource;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataMountResult {
|
||||
SaveDataMountPoint mount_point;
|
||||
uint64_t required_blocks;
|
||||
uint32_t unused;
|
||||
uint32_t mount_status;
|
||||
uint8_t reserved[28];
|
||||
int pad;
|
||||
};
|
||||
|
||||
struct SaveDataParam {
|
||||
char title[128];
|
||||
char sub_title[128];
|
||||
char detail[1024];
|
||||
uint32_t user_param;
|
||||
int pad;
|
||||
int64_t mtime;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataMountInfo {
|
||||
uint64_t blocks;
|
||||
uint64_t free_blocks;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataIcon {
|
||||
void* buf;
|
||||
size_t buf_size;
|
||||
size_t data_size;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataMemoryData {
|
||||
void* buf;
|
||||
size_t buf_size;
|
||||
int64_t offset;
|
||||
uint8_t reserved[40];
|
||||
};
|
||||
|
||||
struct SaveDataMemoryGet2 {
|
||||
int32_t user_id;
|
||||
uint8_t padding[4];
|
||||
SaveDataMemoryData* data;
|
||||
SaveDataParam* param;
|
||||
SaveDataIcon* icon;
|
||||
uint32_t slot_id;
|
||||
uint8_t reserved[28];
|
||||
};
|
||||
|
||||
struct SaveDataMemorySetup2 {
|
||||
uint32_t option;
|
||||
int32_t user_id;
|
||||
size_t memory_size;
|
||||
size_t icon_memory_size;
|
||||
const SaveDataParam* init_param;
|
||||
const SaveDataIcon* init_icon;
|
||||
uint32_t slot_id;
|
||||
uint8_t reserved[20];
|
||||
};
|
||||
|
||||
struct SaveDataMemorySetupResult {
|
||||
size_t existed_memory_size;
|
||||
uint8_t reserved[16];
|
||||
};
|
||||
|
||||
struct SaveDataMemorySet2 {
|
||||
int32_t user_id;
|
||||
uint8_t padding[4];
|
||||
const SaveDataMemoryData* data;
|
||||
const SaveDataParam* param;
|
||||
const SaveDataIcon* icon;
|
||||
uint32_t data_num;
|
||||
uint32_t slot_id;
|
||||
uint8_t reserved[24];
|
||||
};
|
||||
|
||||
struct SaveDataTransferringMount {
|
||||
int32_t user_id;
|
||||
const SceSaveDataTitleId* title_id;
|
||||
const SceSaveDataDirName* dir_name;
|
||||
const void* fingerprint;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataPrepareParam {
|
||||
int32_t resource;
|
||||
uint32_t prepare_mode;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataCommitParam {
|
||||
int32_t resource;
|
||||
uint32_t commit_mode;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataDelete {
|
||||
int32_t user_id;
|
||||
int32_t pad;
|
||||
const SceSaveDataTitleId* title_id;
|
||||
const SceSaveDataDirName* dir_name;
|
||||
uint32_t unused;
|
||||
uint8_t reserved[32];
|
||||
int32_t pad2;
|
||||
};
|
||||
|
||||
struct SaveDataEvent {
|
||||
uint32_t type;
|
||||
int32_t error_code;
|
||||
int32_t user_id;
|
||||
uint8_t padding[4];
|
||||
SceSaveDataTitleId title_id;
|
||||
SceSaveDataDirName dir_name;
|
||||
uint8_t reserved[40];
|
||||
};
|
||||
|
||||
struct SaveDataBackup {
|
||||
int32_t user_id;
|
||||
int32_t pad;
|
||||
const SceSaveDataTitleId* title_id;
|
||||
const SceSaveDataDirName* dir_name;
|
||||
const void* fingerprint;
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
static constexpr uint32_t SAVE_DATA_UMOUNT_MODE_BACKUP_ASYNC = (1u << 16u);
|
||||
static constexpr uint32_t SAVE_DATA_COMMIT_MODE_BACKUP_ASYNC = 1u;
|
||||
|
||||
static constexpr uint32_t SAVE_DATA_EVENT_TYPE_UMOUNT_BACKUP_END = 1u;
|
||||
static constexpr uint32_t SAVE_DATA_EVENT_TYPE_BACKUP_END = 2u;
|
||||
static constexpr uint32_t SAVE_DATA_EVENT_TYPE_COMMIT_BACKUP_END = 4u;
|
||||
|
||||
static std::vector<uint8_t> g_save_data_memory(0x10000);
|
||||
static int32_t g_next_transaction_resource = 1;
|
||||
static std::deque<SaveDataEvent> g_save_data_events;
|
||||
|
||||
static std::string get_title_id() {
|
||||
std::string title_id;
|
||||
if (!Loader::SystemContentParamSfoGetString("TITLE_ID", &title_id) || title_id.empty()) {
|
||||
title_id = "UNKNOWN";
|
||||
}
|
||||
|
||||
return title_id;
|
||||
}
|
||||
|
||||
static void queue_save_data_event(uint32_t type, int32_t user_id,
|
||||
const SceSaveDataTitleId* title_id,
|
||||
const SceSaveDataDirName* dir_name, int32_t error_code = OK) {
|
||||
SaveDataEvent event = {};
|
||||
event.type = type;
|
||||
event.error_code = error_code;
|
||||
event.user_id = user_id;
|
||||
if (title_id != nullptr) {
|
||||
std::memcpy(&event.title_id, title_id, sizeof(event.title_id));
|
||||
}
|
||||
if (dir_name != nullptr) {
|
||||
std::memcpy(&event.dir_name, dir_name, sizeof(event.dir_name));
|
||||
}
|
||||
|
||||
g_save_data_events.push_back(event);
|
||||
if (g_save_data_events.size() > 20) {
|
||||
g_save_data_events.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
static bool dir_name_match(const char* str, const char* pattern) {
|
||||
while (*str != '\0' && *pattern != '\0') {
|
||||
if (*pattern == '%') {
|
||||
for (const char* s = str;; s++) {
|
||||
if (dir_name_match(s, pattern + 1)) {
|
||||
return true;
|
||||
}
|
||||
if (*s == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (*pattern == '_') {
|
||||
str++;
|
||||
pattern++;
|
||||
continue;
|
||||
}
|
||||
if (*pattern != *str) {
|
||||
return false;
|
||||
}
|
||||
str++;
|
||||
pattern++;
|
||||
}
|
||||
return *str == '\0' && *pattern == '\0';
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataInitialize3(const void* /*init*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
// EXIT_NOT_IMPLEMENTED(init != nullptr);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataTerminate() {
|
||||
PRINT_NAME();
|
||||
|
||||
g_save_data_events.clear();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataCreateTransactionResource(uint32_t size) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t size = %" PRIu32 "\n", size);
|
||||
|
||||
return g_next_transaction_resource++;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDeleteTransactionResource(int32_t resource) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t resource = %" PRId32 "\n", resource);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDirNameSearch(const SaveDataDirNameSearchCond* cond,
|
||||
SaveDataDirNameSearchResult* result) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (cond == nullptr || result == nullptr ||
|
||||
static_cast<uint32_t>(cond->key) > static_cast<uint32_t>(SaveDataSortKey::FreeBlocks) ||
|
||||
static_cast<uint32_t>(cond->order) > static_cast<uint32_t>(SaveDataSortOrder::Descent)) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t user_id = %d\n"
|
||||
"\t title_id = %s\n"
|
||||
"\t dir_name = %s\n"
|
||||
"\t key = %" PRIu32 "\n"
|
||||
"\t order = %" PRIu32 "\n"
|
||||
"\t dir_names_num = %" PRIu32 "\n",
|
||||
cond->user_id, cond->title_id != nullptr ? cond->title_id->data : "<default>",
|
||||
cond->dir_name != nullptr ? cond->dir_name->data : "<all>",
|
||||
static_cast<uint32_t>(cond->key), static_cast<uint32_t>(cond->order),
|
||||
result->dir_names_num);
|
||||
|
||||
result->hit_num = 0;
|
||||
result->pad = 0;
|
||||
result->set_num = 0;
|
||||
std::memset(result->reserved, 0, sizeof(result->reserved));
|
||||
result->pad2 = 0;
|
||||
|
||||
std::vector<std::string> dir_list;
|
||||
std::string root =
|
||||
Common::FixDirectorySlash((std::string(SAVE_DATA_DIR) + "/" + get_title_id()));
|
||||
|
||||
if (Common::File::IsDirectoryExisting(root)) {
|
||||
for (const auto& entry: Common::File::GetDirEntries(root)) {
|
||||
if (!entry.is_file && !Common::StartsWith(entry.name, "sce_")) {
|
||||
if (cond->dir_name == nullptr || cond->dir_name->data[0] == '\0' ||
|
||||
dir_name_match(Common::ToLower(entry.name).c_str(),
|
||||
Common::ToLower(std::string(cond->dir_name->data)).c_str())) {
|
||||
dir_list.push_back(entry.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(dir_list.begin(), dir_list.end(), [](const std::string& a, const std::string& b) {
|
||||
return std::strcmp(a.c_str(), b.c_str()) < 0;
|
||||
});
|
||||
|
||||
if (cond->order == SaveDataSortOrder::Descent) {
|
||||
std::vector<std::string> reversed;
|
||||
for (size_t i = dir_list.size(); i > 0; i--) {
|
||||
reversed.push_back(dir_list[i - 1]);
|
||||
}
|
||||
dir_list = reversed;
|
||||
}
|
||||
|
||||
auto max_count =
|
||||
(result->dir_names_num < dir_list.size() ? result->dir_names_num : dir_list.size());
|
||||
|
||||
result->hit_num = static_cast<uint32_t>(dir_list.size());
|
||||
result->set_num = static_cast<uint32_t>(max_count);
|
||||
|
||||
for (size_t i = 0; i < max_count; i++) {
|
||||
std::snprintf(result->dir_names[i].data, sizeof(result->dir_names[i].data), "%s",
|
||||
dir_list[i].c_str());
|
||||
if (result->params != nullptr) {
|
||||
result->params[i] = {};
|
||||
}
|
||||
if (result->infos != nullptr) {
|
||||
result->infos[i] = {};
|
||||
result->infos[i].blocks = SAVE_DATA_BLOCKS_MAX;
|
||||
result->infos[i].free_blocks = SAVE_DATA_BLOCKS_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataMount3(const SaveDataMount3* mount, SaveDataMountResult* mount_result) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(mount == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(mount_result == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(mount->dir_name == nullptr);
|
||||
|
||||
LOGF("\t user_id = %d\n"
|
||||
"\t dir_name = %s\n"
|
||||
"\t blocks = %" PRIu64 "\n"
|
||||
"\t system_blocks = %" PRIu64 "\n"
|
||||
"\t mount_mode = %" PRIu32 "\n"
|
||||
"\t resource = %" PRId32 "\n",
|
||||
mount->user_id, mount->dir_name->data, mount->blocks, mount->system_blocks,
|
||||
mount->mount_mode, mount->resource);
|
||||
|
||||
*mount_result = {};
|
||||
|
||||
std::string mount_dir = std::string(SAVE_DATA_DIR) + "/" + get_title_id() + "/" +
|
||||
std::string(mount->dir_name->data);
|
||||
std::string mount_point = SAVE_DATA_POINT;
|
||||
bool create = ((mount->mount_mode & 4u) != 0);
|
||||
bool create2 = ((mount->mount_mode & 32u) != 0);
|
||||
bool open = (!create && !create2 && ((mount->mount_mode & 3u) != 0));
|
||||
|
||||
if (!create && !create2 && !open) {
|
||||
EXIT("unknown mount mode: %u", mount->mount_mode);
|
||||
}
|
||||
|
||||
if (open && !Common::File::IsDirectoryExisting(mount_dir)) {
|
||||
return SAVE_DATA_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (create && Common::File::IsDirectoryExisting(mount_dir)) {
|
||||
return SAVE_DATA_ERROR_EXISTS;
|
||||
}
|
||||
|
||||
bool created = false;
|
||||
if ((create || create2) && !Common::File::IsDirectoryExisting(mount_dir)) {
|
||||
Common::File::CreateDirectories(mount_dir);
|
||||
created = true;
|
||||
|
||||
EXIT_NOT_IMPLEMENTED((!Common::File::IsDirectoryExisting(mount_dir)));
|
||||
}
|
||||
|
||||
LibKernel::FileSystem::Mount(mount_dir, mount_point);
|
||||
|
||||
int s = snprintf(mount_result->mount_point.data, 16, "%s", mount_point.c_str());
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(s >= 16);
|
||||
|
||||
mount_result->required_blocks = 0;
|
||||
mount_result->mount_status = (created ? 1 : 0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2* setup_param,
|
||||
SaveDataMemorySetupResult* result) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (setup_param == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t option = 0x%08" PRIx32 "\n"
|
||||
"\t user_id = %" PRId32 "\n"
|
||||
"\t memory_size = %" PRIu64 "\n"
|
||||
"\t icon_memory_size = %" PRIu64 "\n"
|
||||
"\t slot_id = %" PRIu32 "\n",
|
||||
setup_param->option, setup_param->user_id, static_cast<uint64_t>(setup_param->memory_size),
|
||||
static_cast<uint64_t>(setup_param->icon_memory_size), setup_param->slot_id);
|
||||
|
||||
if (setup_param->memory_size > g_save_data_memory.size()) {
|
||||
g_save_data_memory.resize(setup_param->memory_size);
|
||||
}
|
||||
|
||||
if (result != nullptr) {
|
||||
*result = {};
|
||||
result->existed_memory_size = g_save_data_memory.size();
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataGetSaveDataMemory2(SaveDataMemoryGet2* get_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (get_param == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t user_id = %" PRId32 "\n"
|
||||
"\t data = 0x%016" PRIx64 "\n"
|
||||
"\t param = 0x%016" PRIx64 "\n"
|
||||
"\t icon = 0x%016" PRIx64 "\n"
|
||||
"\t slot_id = %" PRIu32 "\n",
|
||||
get_param->user_id, reinterpret_cast<uint64_t>(get_param->data),
|
||||
reinterpret_cast<uint64_t>(get_param->param), reinterpret_cast<uint64_t>(get_param->icon),
|
||||
get_param->slot_id);
|
||||
|
||||
if (get_param->data != nullptr) {
|
||||
auto* data = get_param->data;
|
||||
if (data->buf == nullptr || data->offset < 0) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
const auto offset = static_cast<size_t>(data->offset);
|
||||
if (offset + data->buf_size > g_save_data_memory.size()) {
|
||||
g_save_data_memory.resize(offset + data->buf_size);
|
||||
}
|
||||
std::memcpy(data->buf, g_save_data_memory.data() + offset, data->buf_size);
|
||||
}
|
||||
if (get_param->param != nullptr) {
|
||||
std::memset(get_param->param, 0, sizeof(*get_param->param));
|
||||
}
|
||||
if (get_param->icon != nullptr) {
|
||||
get_param->icon->data_size = 0;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataSetSaveDataMemory2(const SaveDataMemorySet2* set_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (set_param == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t user_id = %" PRId32 "\n"
|
||||
"\t data = 0x%016" PRIx64 "\n"
|
||||
"\t param = 0x%016" PRIx64 "\n"
|
||||
"\t icon = 0x%016" PRIx64 "\n"
|
||||
"\t data_num = %" PRIu32 "\n"
|
||||
"\t slot_id = %" PRIu32 "\n",
|
||||
set_param->user_id, reinterpret_cast<uint64_t>(set_param->data),
|
||||
reinterpret_cast<uint64_t>(set_param->param), reinterpret_cast<uint64_t>(set_param->icon),
|
||||
set_param->data_num, set_param->slot_id);
|
||||
|
||||
const uint32_t data_num = (set_param->data_num == 0 ? 1 : set_param->data_num);
|
||||
if (set_param->data != nullptr) {
|
||||
for (uint32_t i = 0; i < data_num; i++) {
|
||||
const auto& data = set_param->data[i];
|
||||
if (data.buf == nullptr || data.offset < 0) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
const auto offset = static_cast<size_t>(data.offset);
|
||||
if (offset + data.buf_size > g_save_data_memory.size()) {
|
||||
g_save_data_memory.resize(offset + data.buf_size);
|
||||
}
|
||||
std::memcpy(g_save_data_memory.data() + offset, data.buf, data.buf_size);
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataTransferringMount(const SaveDataTransferringMount* mount,
|
||||
SaveDataMountResult* mount_result) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mount == nullptr || mount_result == nullptr || mount->dir_name == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t user_id = %" PRId32 "\n"
|
||||
"\t title_id = %s\n"
|
||||
"\t dir_name = %s\n",
|
||||
mount->user_id, mount->title_id != nullptr ? mount->title_id->data : "<null>",
|
||||
mount->dir_name->data);
|
||||
|
||||
*mount_result = {};
|
||||
|
||||
std::string mount_dir = std::string(SAVE_DATA_DIR) + "/" + get_title_id() + "/" +
|
||||
std::string(mount->dir_name->data);
|
||||
std::string mount_point = SAVE_DATA_POINT;
|
||||
|
||||
if (!Common::File::IsDirectoryExisting(mount_dir)) {
|
||||
Common::File::CreateDirectories(mount_dir);
|
||||
}
|
||||
|
||||
LibKernel::FileSystem::Mount(mount_dir, mount_point);
|
||||
|
||||
int s = snprintf(mount_result->mount_point.data, 16, "%s", mount_point.c_str());
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(s >= 16);
|
||||
|
||||
mount_result->required_blocks = 0;
|
||||
mount_result->mount_status = 1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataUmount2(uint32_t mode, const SaveDataMountPoint* mount_point) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mount_point == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t mode = %" PRIu32 "\n"
|
||||
"\t mount_point = %s\n",
|
||||
mode, mount_point->data);
|
||||
|
||||
if ((mode & SAVE_DATA_UMOUNT_MODE_BACKUP_ASYNC) != 0) {
|
||||
queue_save_data_event(SAVE_DATA_EVENT_TYPE_UMOUNT_BACKUP_END, 0, nullptr, nullptr);
|
||||
}
|
||||
|
||||
LibKernel::FileSystem::Umount(std::string(mount_point->data));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataPrepare(const SaveDataMountPoint* mount_point,
|
||||
const SaveDataPrepareParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mount_point == nullptr || param == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t mount_point = %s\n"
|
||||
"\t resource = %" PRId32 "\n"
|
||||
"\t prepare_mode = %" PRIu32 "\n",
|
||||
mount_point->data, param->resource, param->prepare_mode);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataCommit(const SaveDataCommitParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (param == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t resource = %" PRId32 "\n"
|
||||
"\t commit_mode = %" PRIu32 "\n",
|
||||
param->resource, param->commit_mode);
|
||||
|
||||
if ((param->commit_mode & SAVE_DATA_COMMIT_MODE_BACKUP_ASYNC) != 0) {
|
||||
queue_save_data_event(SAVE_DATA_EVENT_TYPE_COMMIT_BACKUP_END, 0, nullptr, nullptr);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataDelete(const SaveDataDelete* del) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (del == nullptr || del->dir_name == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t user_id = %" PRId32 "\n"
|
||||
"\t title_id = %s\n"
|
||||
"\t dir_name = %s\n",
|
||||
del->user_id, del->title_id != nullptr ? del->title_id->data : "<default>",
|
||||
del->dir_name->data);
|
||||
|
||||
std::string dir =
|
||||
std::string(SAVE_DATA_DIR) + "/" + get_title_id() + "/" + std::string(del->dir_name->data);
|
||||
if (Common::File::IsDirectoryExisting(dir)) {
|
||||
Common::File::DeleteDirectory(dir);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataGetParam(const SaveDataMountPoint* mount_point, uint32_t param_type,
|
||||
void* param_buf, size_t param_buf_size, size_t* got_size) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mount_point == nullptr || param_buf == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t mount_point = %s\n"
|
||||
"\t param_type = %u\n"
|
||||
"\t param_buf_size = %" PRIu64 "\n",
|
||||
mount_point->data, param_type, param_buf_size);
|
||||
|
||||
if (param_type == 0) {
|
||||
if (param_buf_size < sizeof(SaveDataParam)) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
std::memset(param_buf, 0, sizeof(SaveDataParam));
|
||||
if (got_size != nullptr) {
|
||||
*got_size = sizeof(SaveDataParam);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
std::memset(param_buf, 0, param_buf_size);
|
||||
if (got_size != nullptr) {
|
||||
*got_size = param_buf_size;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataLoadIcon(const SaveDataMountPoint* mount_point, SaveDataIcon* icon) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mount_point == nullptr || icon == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t mount_point = %s\n"
|
||||
"\t buf = %016" PRIx64 "\n"
|
||||
"\t buf_size = %" PRIu64 "\n",
|
||||
mount_point->data, reinterpret_cast<uint64_t>(icon->buf), icon->buf_size);
|
||||
|
||||
icon->data_size = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataSaveIconByPath(const SaveDataMountPoint* mount_point, const char* path) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mount_point == nullptr || path == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t mount_point = %s\n"
|
||||
"\t path = %s\n",
|
||||
mount_point->data, path);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataSyncSaveDataMemory(const void* sync_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t sync_param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(sync_param));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataGetEventResult(const void* event_param, SaveDataEvent* event) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t event_param = 0x%016" PRIx64 "\n"
|
||||
"\t event = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(event_param), reinterpret_cast<uint64_t>(event));
|
||||
|
||||
if (event == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
if (g_save_data_events.empty()) {
|
||||
return SAVE_DATA_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
*event = g_save_data_events.front();
|
||||
g_save_data_events.pop_front();
|
||||
|
||||
LOGF("\t type = %" PRIu32 "\n"
|
||||
"\t error_code = %" PRId32 "\n"
|
||||
"\t user_id = %" PRId32 "\n"
|
||||
"\t title_id = %.10s\n"
|
||||
"\t dir_name = %.32s\n",
|
||||
event->type, event->error_code, event->user_id, event->title_id.data,
|
||||
event->dir_name.data);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataBackup(const SaveDataBackup* backup) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t backup = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(backup));
|
||||
|
||||
if (backup == nullptr || backup->dir_name == nullptr) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
LOGF("\t user_id = %" PRId32 "\n"
|
||||
"\t title_id = %.10s\n"
|
||||
"\t dir_name = %.32s\n",
|
||||
backup->user_id, backup->title_id != nullptr ? backup->title_id->data : "<default>",
|
||||
backup->dir_name->data);
|
||||
|
||||
queue_save_data_event(SAVE_DATA_EVENT_TYPE_BACKUP_END, backup->user_id, backup->title_id,
|
||||
backup->dir_name);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataSetParam(const SaveDataMountPoint* mount_point, uint32_t param_type,
|
||||
const void* param_buf, size_t param_buf_size) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(mount_point == nullptr);
|
||||
|
||||
LOGF("\t mount_point = %s\n"
|
||||
"\t param_type = %u\n"
|
||||
"\t param_buf_size = %" PRIu64 "\n",
|
||||
mount_point->data, param_type, param_buf_size);
|
||||
|
||||
if (param_type == 0) {
|
||||
const auto* p = static_cast<const SaveDataParam*>(param_buf);
|
||||
|
||||
LOGF("\t title = %s\n"
|
||||
"\t sub_title = %s\n"
|
||||
"\t detail = %s\n"
|
||||
"\t user_param = %u\n",
|
||||
p->title, p->sub_title, p->detail, p->user_param);
|
||||
} else {
|
||||
LOGF("\t unsupported param_type, accepting as no-op\n");
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataGetMountInfo(const SaveDataMountPoint* mount_point,
|
||||
SaveDataMountInfo* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(mount_point == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(info == nullptr);
|
||||
|
||||
*info = {};
|
||||
|
||||
info->blocks = SAVE_DATA_BLOCKS_MAX;
|
||||
info->free_blocks = SAVE_DATA_BLOCKS_MAX;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI SaveDataSaveIcon(const SaveDataMountPoint* mount_point,
|
||||
const SaveDataIcon* icon) {
|
||||
EXIT_NOT_IMPLEMENTED(mount_point == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(icon == nullptr);
|
||||
|
||||
LOGF("\t buf = %016" PRIx64 "\n"
|
||||
"\t buf_size = %" PRIu64 "\n"
|
||||
"\t data_size = %" PRIu64 "\n",
|
||||
reinterpret_cast<uint64_t>(icon->buf), icon->buf_size, icon->data_size);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace SaveData
|
||||
|
||||
namespace LibSaveDataNative {
|
||||
|
||||
LIB_VERSION("SaveData_native", 1, "SaveData_native", 1, 1);
|
||||
|
||||
LIB_DEFINE(InitSaveDataNative_1) {
|
||||
LIB_FUNC("TywrFKCoLGY", ::Libs::SaveData::SaveDataInitialize3);
|
||||
LIB_FUNC("dyIhnXq-0SM", ::Libs::SaveData::SaveDataDirNameSearch);
|
||||
LIB_FUNC("PHnuI4LhuRk", ::Libs::SaveData::SaveDataDirNameSearch);
|
||||
LIB_FUNC("ZP4e7rlzOUk", ::Libs::SaveData::SaveDataMount3);
|
||||
LIB_FUNC("gjRZNnw0JPE", ::Libs::SaveData::SaveDataCreateTransactionResource);
|
||||
LIB_FUNC("lJUQuaKqoKY", ::Libs::SaveData::SaveDataDeleteTransactionResource);
|
||||
LIB_FUNC("sDCBrmc61XU", ::Libs::SaveData::SaveDataPrepare);
|
||||
LIB_FUNC("ie7qhZ4X0Cc", ::Libs::SaveData::SaveDataCommit);
|
||||
LIB_FUNC("oQySEUfgXRA", ::Libs::SaveData::SaveDataSetupSaveDataMemory2);
|
||||
LIB_FUNC("QwOO7vegnV8", ::Libs::SaveData::SaveDataGetSaveDataMemory2);
|
||||
LIB_FUNC("cduy9v4YmT4", ::Libs::SaveData::SaveDataSetSaveDataMemory2);
|
||||
LIB_FUNC("wiT9jeC7xPw", ::Libs::SaveData::SaveDataSyncSaveDataMemory);
|
||||
LIB_FUNC("j8xKtiFj0SY", ::Libs::SaveData::SaveDataGetEventResult);
|
||||
LIB_FUNC("WAzWTZm1H+I", ::Libs::SaveData::SaveDataTransferringMount);
|
||||
LIB_FUNC("RjMlsR8EXrw", ::Libs::SaveData::SaveDataTransferringMount);
|
||||
LIB_FUNC("z1JA8-iJt3k", ::Libs::SaveData::SaveDataBackup);
|
||||
LIB_FUNC("uW4vfTwMQVo", ::Libs::SaveData::SaveDataUmount2);
|
||||
LIB_FUNC("S1GkePI17zQ", ::Libs::SaveData::SaveDataDelete);
|
||||
LIB_FUNC("85zul--eGXs", ::Libs::SaveData::SaveDataSetParam);
|
||||
LIB_FUNC("XgvSuIdnMlw", ::Libs::SaveData::SaveDataGetParam);
|
||||
LIB_FUNC("65VH0Qaaz6s", ::Libs::SaveData::SaveDataGetMountInfo);
|
||||
LIB_FUNC("c88Yy54Mx0w", ::Libs::SaveData::SaveDataSaveIcon);
|
||||
LIB_FUNC("Z7z6HXWORJY", ::Libs::SaveData::SaveDataSaveIconByPath);
|
||||
LIB_FUNC("cGjO3wM3V28", ::Libs::SaveData::SaveDataLoadIcon);
|
||||
LIB_FUNC("X4MYzukPc3g", ::Libs::SaveData::SaveDataDirNameSearch);
|
||||
LIB_FUNC("yKDy8S5yLA0", ::Libs::SaveData::SaveDataTerminate);
|
||||
}
|
||||
|
||||
} // namespace LibSaveDataNative
|
||||
|
||||
LIB_DEFINE(InitSaveData_1) {
|
||||
LIB_FUNC("TywrFKCoLGY", SaveData::SaveDataInitialize3);
|
||||
LIB_FUNC("dyIhnXq-0SM", SaveData::SaveDataDirNameSearch);
|
||||
LIB_FUNC("ZP4e7rlzOUk", SaveData::SaveDataMount3);
|
||||
LIB_FUNC("gjRZNnw0JPE", SaveData::SaveDataCreateTransactionResource);
|
||||
LIB_FUNC("lJUQuaKqoKY", SaveData::SaveDataDeleteTransactionResource);
|
||||
LIB_FUNC("sDCBrmc61XU", SaveData::SaveDataPrepare);
|
||||
LIB_FUNC("ie7qhZ4X0Cc", SaveData::SaveDataCommit);
|
||||
LIB_FUNC("oQySEUfgXRA", SaveData::SaveDataSetupSaveDataMemory2);
|
||||
LIB_FUNC("QwOO7vegnV8", SaveData::SaveDataGetSaveDataMemory2);
|
||||
LIB_FUNC("cduy9v4YmT4", SaveData::SaveDataSetSaveDataMemory2);
|
||||
LIB_FUNC("wiT9jeC7xPw", SaveData::SaveDataSyncSaveDataMemory);
|
||||
LIB_FUNC("j8xKtiFj0SY", SaveData::SaveDataGetEventResult);
|
||||
LIB_FUNC("WAzWTZm1H+I", SaveData::SaveDataTransferringMount);
|
||||
LIB_FUNC("RjMlsR8EXrw", SaveData::SaveDataTransferringMount);
|
||||
LIB_FUNC("z1JA8-iJt3k", SaveData::SaveDataBackup);
|
||||
LIB_FUNC("uW4vfTwMQVo", SaveData::SaveDataUmount2);
|
||||
LIB_FUNC("S1GkePI17zQ", SaveData::SaveDataDelete);
|
||||
LIB_FUNC("85zul--eGXs", SaveData::SaveDataSetParam);
|
||||
LIB_FUNC("XgvSuIdnMlw", SaveData::SaveDataGetParam);
|
||||
LIB_FUNC("65VH0Qaaz6s", SaveData::SaveDataGetMountInfo);
|
||||
LIB_FUNC("c88Yy54Mx0w", SaveData::SaveDataSaveIcon);
|
||||
LIB_FUNC("Z7z6HXWORJY", SaveData::SaveDataSaveIconByPath);
|
||||
LIB_FUNC("cGjO3wM3V28", SaveData::SaveDataLoadIcon);
|
||||
LIB_FUNC("X4MYzukPc3g", SaveData::SaveDataDirNameSearch);
|
||||
LIB_FUNC("yKDy8S5yLA0", SaveData::SaveDataTerminate);
|
||||
|
||||
LibSaveDataNative::InitSaveDataNative_1(s);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,245 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("Share", 1, "Share", 1, 1);
|
||||
|
||||
namespace Share {
|
||||
|
||||
constexpr int SHARE_ERROR_INVALID_PARAM = -2120876030; /* 0x81960002 */
|
||||
constexpr int SHARE_ERROR_NOT_SUPPORTED = -2120876025; /* 0x81960007 */
|
||||
constexpr int SHARE_REQUEST_ID_INVALID = -1;
|
||||
|
||||
struct ShareCurrentRecordingStatus {
|
||||
uint32_t recording_2k_status;
|
||||
uint32_t recording_4k_status;
|
||||
uint8_t reserved[8];
|
||||
};
|
||||
|
||||
union ShareCurrentStatus {
|
||||
ShareCurrentRecordingStatus recording_status;
|
||||
uint8_t reserved[16];
|
||||
};
|
||||
|
||||
static bool share_feature_flag_valid(uint32_t feature_flags) {
|
||||
constexpr uint32_t share_feature_flag_all = 0xffffffffu;
|
||||
return feature_flags != 0 && (feature_flags & share_feature_flag_all) == feature_flags;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareCaptureScreenshot(const void* param, int32_t* req_id) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t param = 0x%016" PRIx64 "\n"
|
||||
"\t req_id = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(param), reinterpret_cast<uint64_t>(req_id));
|
||||
|
||||
if (req_id != nullptr) {
|
||||
*req_id = SHARE_REQUEST_ID_INVALID;
|
||||
}
|
||||
|
||||
return SHARE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareCaptureScreenshotExtended(const void* extended_param,
|
||||
int32_t* req_id) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t extended_param = 0x%016" PRIx64 "\n"
|
||||
"\t req_id = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(extended_param), reinterpret_cast<uint64_t>(req_id));
|
||||
|
||||
if (req_id != nullptr) {
|
||||
*req_id = SHARE_REQUEST_ID_INVALID;
|
||||
}
|
||||
|
||||
return SHARE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareCaptureVideoClip(const void* param, int32_t* req_id) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t param = 0x%016" PRIx64 "\n"
|
||||
"\t req_id = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(param), reinterpret_cast<uint64_t>(req_id));
|
||||
|
||||
if (req_id != nullptr) {
|
||||
*req_id = SHARE_REQUEST_ID_INVALID;
|
||||
}
|
||||
|
||||
return SHARE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareCaptureVideoClipExtended(const void* extended_param,
|
||||
int32_t* req_id) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t extended_param = 0x%016" PRIx64 "\n"
|
||||
"\t req_id = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(extended_param), reinterpret_cast<uint64_t>(req_id));
|
||||
|
||||
if (req_id != nullptr) {
|
||||
*req_id = SHARE_REQUEST_ID_INVALID;
|
||||
}
|
||||
|
||||
return SHARE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareUnregisterContentEventCallback(void* callback) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t callback = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(callback));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareOpenMenuForContent(const void* content_id) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t content_id = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(content_id));
|
||||
|
||||
return SHARE_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareSetScreenshotOverlayImage(const char* file_path, int32_t margin_x,
|
||||
int32_t margin_y, int32_t origin) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t file_path = %s\n"
|
||||
"\t margin_x = %d\n"
|
||||
"\t margin_y = %d\n"
|
||||
"\t origin = %d\n",
|
||||
(file_path != nullptr ? file_path : "<null>"), margin_x, margin_y, origin);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareSetCaptureSource(uint32_t feature_flags, const void* tap_point) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t feature_flags = 0x%08" PRIx32 "\n"
|
||||
"\t tap_point = 0x%016" PRIx64 "\n",
|
||||
feature_flags, reinterpret_cast<uint64_t>(tap_point));
|
||||
|
||||
if (!share_feature_flag_valid(feature_flags)) {
|
||||
return SHARE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareSetContentParam(const char* content_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t content_param = %s\n", (content_param != nullptr ? content_param : "<null>"));
|
||||
|
||||
if (content_param == nullptr) {
|
||||
return SHARE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareSetContentParamForApplicationTitle(const char* application_title) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t application_title = %s\n",
|
||||
(application_title != nullptr ? application_title : "<null>"));
|
||||
|
||||
if (application_title == nullptr) {
|
||||
return SHARE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareRegisterContentEventCallback(void* callback, void* user_data) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t callback = 0x%016" PRIx64 "\n"
|
||||
"\t user_data = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(callback), reinterpret_cast<uint64_t>(user_data));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareGetCurrentStatus(uint32_t feature_flag, ShareCurrentStatus* status) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t feature_flag = 0x%08" PRIx32 "\n"
|
||||
"\t status = 0x%016" PRIx64 "\n",
|
||||
feature_flag, reinterpret_cast<uint64_t>(status));
|
||||
|
||||
if (!share_feature_flag_valid(feature_flag) || status == nullptr) {
|
||||
return SHARE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
std::memset(status, 0, sizeof(*status));
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareGetRunningStatus(uint32_t* feature_flags) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t feature_flags = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(feature_flags));
|
||||
|
||||
if (feature_flags == nullptr) {
|
||||
return SHARE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
*feature_flags = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareFeaturePermit(uint32_t feature_flags) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t feature_flags = 0x%08" PRIx32 "\n", feature_flags);
|
||||
|
||||
if (!share_feature_flag_valid(feature_flags)) {
|
||||
return SHARE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int ShareFeatureProhibit(uint32_t feature_flags) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t feature_flags = 0x%08" PRIx32 "\n", feature_flags);
|
||||
|
||||
if (!share_feature_flag_valid(feature_flags)) {
|
||||
return SHARE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace Share
|
||||
|
||||
LIB_DEFINE(InitShare_1) {
|
||||
LIB_FUNC("4jt8pMDudgk", Share::ShareCaptureVideoClip);
|
||||
LIB_FUNC("5wjxESwX68I", Share::ShareFeatureProhibit);
|
||||
LIB_FUNC("7QZtURYnXG4", Share::ShareSetContentParam);
|
||||
LIB_FUNC("8qAJ0Jd58-Q", Share::ShareOpenMenuForContent);
|
||||
LIB_FUNC("AcDNpEpoT9U", Share::ShareCaptureVideoClipExtended);
|
||||
LIB_FUNC("ErH6tKS7fzE", Share::ShareCaptureScreenshot);
|
||||
LIB_FUNC("GQTObcITIXI", Share::ShareCaptureScreenshotExtended);
|
||||
LIB_FUNC("KnsfHKmZqFA", Share::ShareUnregisterContentEventCallback);
|
||||
LIB_FUNC("ORspsWDXPps", Share::ShareSetContentParamForApplicationTitle);
|
||||
LIB_FUNC("QNop2YAtIDE", Share::ShareGetCurrentStatus);
|
||||
LIB_FUNC("Sygnk9dr5WQ", Share::ShareRegisterContentEventCallback);
|
||||
LIB_FUNC("T64o-315wbg", Share::ShareSetScreenshotOverlayImage);
|
||||
LIB_FUNC("YBiIdcDPrxs", Share::ShareFeaturePermit);
|
||||
LIB_FUNC("crFxyW3HdK0", Share::ShareGetRunningStatus);
|
||||
LIB_FUNC("kCurUZVFqcI", Share::ShareSetCaptureSource);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("Sysmodule", 1, "Sysmodule", 1, 1);
|
||||
|
||||
namespace LibKernel {
|
||||
struct ModuleInfoForUnwind;
|
||||
int KYTY_SYSV_ABI KernelGetModuleInfoForUnwind(uint64_t addr, int flags, ModuleInfoForUnwind* info);
|
||||
} // namespace LibKernel
|
||||
|
||||
namespace Sysmodule {
|
||||
|
||||
static KYTY_SYSV_ABI int SysmoduleGetModuleInfoForUnwind(uint64_t addr, int flags,
|
||||
LibKernel::ModuleInfoForUnwind* info) {
|
||||
return LibKernel::KernelGetModuleInfoForUnwind(addr, flags, info);
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int SysmoduleLoadModule(uint16_t id) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t id = %d\n", static_cast<int>(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int SysmoduleUnloadModule(uint16_t id) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t id = %d\n", static_cast<int>(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int SysmoduleLoadModuleInternalWithArg(uint16_t id, int arg1, int arg2,
|
||||
int arg3, int* ret) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t id = %d\n", static_cast<int>(id));
|
||||
|
||||
EXIT_IF(arg1 != 0);
|
||||
EXIT_IF(arg2 != 0);
|
||||
EXIT_IF(arg3 != 0);
|
||||
EXIT_IF(ret == nullptr);
|
||||
|
||||
*ret = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int SysmoduleIsLoaded(uint16_t id) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t id = %d\n", static_cast<int>(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Sysmodule
|
||||
|
||||
LIB_DEFINE(InitSysmodule_1) {
|
||||
LIB_FUNC("4fU5yvOkVG4", Sysmodule::SysmoduleGetModuleInfoForUnwind);
|
||||
LIB_FUNC("eR2bZFAAU0Q", Sysmodule::SysmoduleUnloadModule);
|
||||
LIB_FUNC("hHrGoGoNf+s", Sysmodule::SysmoduleLoadModuleInternalWithArg);
|
||||
LIB_FUNC("g8cM39EUZ6o", Sysmodule::SysmoduleLoadModule);
|
||||
LIB_FUNC("fMP5NHUOaMk", Sysmodule::SysmoduleIsLoaded);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,569 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("SystemService", 1, "SystemService", 1, 1);
|
||||
|
||||
namespace SystemService {
|
||||
|
||||
[[maybe_unused]] constexpr int PARAM_ID_LANG = 1;
|
||||
[[maybe_unused]] constexpr int PARAM_ID_DATE_FORMAT = 2;
|
||||
[[maybe_unused]] constexpr int PARAM_ID_TIME_FORMAT = 3;
|
||||
[[maybe_unused]] constexpr int PARAM_ID_TIME_ZONE = 4;
|
||||
[[maybe_unused]] constexpr int PARAM_ID_SUMMERTIME = 5;
|
||||
[[maybe_unused]] constexpr int PARAM_ID_SYSTEM_NAME = 6;
|
||||
[[maybe_unused]] constexpr int PARAM_ID_GAME_PARENTAL_LEVEL = 7;
|
||||
[[maybe_unused]] constexpr int PARAM_ID_ENTER_BUTTON_ASSIGN = 1000;
|
||||
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_JAPANESE = 0;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_ENGLISH_US = 1;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_FRENCH = 2;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_SPANISH = 3;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_GERMAN = 4;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_ITALIAN = 5;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_DUTCH = 6;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_PORTUGUESE_PT = 7;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_RUSSIAN = 8;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_KOREAN = 9;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_CHINESE_T = 10;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_CHINESE_S = 11;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_FINNISH = 12;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_SWEDISH = 13;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_DANISH = 14;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_NORWEGIAN = 15;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_POLISH = 16;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_PORTUGUESE_BR = 17;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_ENGLISH_GB = 18;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_TURKISH = 19;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_SPANISH_LA = 20;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_ARABIC = 21;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_FRENCH_CA = 22;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_CZECH = 23;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_HUNGARIAN = 24;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_GREEK = 25;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_ROMANIAN = 26;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_THAI = 27;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_VIETNAMESE = 28;
|
||||
[[maybe_unused]] constexpr int PARAM_LANG_INDONESIAN = 29;
|
||||
|
||||
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_YYYYMMDD = 0;
|
||||
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_DDMMYYYY = 1;
|
||||
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_MMDDYYYY = 2;
|
||||
|
||||
[[maybe_unused]] constexpr int PARAM_TIME_FORMAT_12HOUR = 0;
|
||||
[[maybe_unused]] constexpr int PARAM_TIME_FORMAT_24HOUR = 1;
|
||||
|
||||
[[maybe_unused]] constexpr int MAX_SYSTEM_NAME_LENGTH = 65;
|
||||
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_OFF = 0;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL01 = 1;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL02 = 2;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL03 = 3;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL04 = 4;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL05 = 5;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL06 = 6;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL07 = 7;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL08 = 8;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL09 = 9;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL10 = 10;
|
||||
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL11 = 11;
|
||||
|
||||
[[maybe_unused]] constexpr int PARAM_ENTER_BUTTON_ASSIGN_CIRCLE = 0;
|
||||
[[maybe_unused]] constexpr int PARAM_ENTER_BUTTON_ASSIGN_CROSS = 1;
|
||||
|
||||
struct SystemServiceStatus {
|
||||
int32_t event_num = 0;
|
||||
bool is_system_ui_overlaid = false;
|
||||
bool is_in_background_execution = false;
|
||||
bool is_vr_play_area_overlaid = false;
|
||||
uint8_t reserved[127] = {};
|
||||
};
|
||||
|
||||
struct SystemServiceEvent {
|
||||
int32_t event_type;
|
||||
uint8_t data[8192];
|
||||
};
|
||||
|
||||
struct SystemServiceDisplaySafeAreaInfo {
|
||||
float ratio;
|
||||
uint8_t reserved[128];
|
||||
};
|
||||
|
||||
struct SystemServiceHdrToneMapLuminance {
|
||||
float max_full_frame_tone_map_luminance;
|
||||
float max_tone_map_luminance;
|
||||
float min_tone_map_luminance;
|
||||
};
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceHideSplashScreen() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceParamGetInt(int param_id, int* value) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (value == nullptr) {
|
||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
int v = 0;
|
||||
|
||||
switch (param_id) {
|
||||
case PARAM_ID_LANG: v = PARAM_LANG_ENGLISH_US; break;
|
||||
case PARAM_ID_DATE_FORMAT: v = PARAM_DATE_FORMAT_DDMMYYYY; break;
|
||||
case PARAM_ID_TIME_FORMAT: v = PARAM_TIME_FORMAT_24HOUR; break;
|
||||
case PARAM_ID_TIME_ZONE: v = +180; break;
|
||||
case PARAM_ID_SUMMERTIME: v = 0; break;
|
||||
case PARAM_ID_GAME_PARENTAL_LEVEL: v = PARAM_GAME_PARENTAL_OFF; break;
|
||||
case PARAM_ID_ENTER_BUTTON_ASSIGN: v = PARAM_ENTER_BUTTON_ASSIGN_CROSS; break;
|
||||
default: EXIT("unknown param_id: %d\n", param_id);
|
||||
}
|
||||
|
||||
LOGF(" %d = %d\n", param_id, v);
|
||||
|
||||
*value = v;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceParamGetString(int param_id, char* buf, size_t buf_size) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (buf == nullptr || buf_size == 0) {
|
||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
const char* value = nullptr;
|
||||
switch (param_id) {
|
||||
case PARAM_ID_SYSTEM_NAME: value = "Kyty"; break;
|
||||
default: EXIT("unknown string param_id: %d\n", param_id);
|
||||
}
|
||||
|
||||
const auto len = std::strlen(value);
|
||||
if (len + 1 > buf_size) {
|
||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
std::memcpy(buf, value, len + 1);
|
||||
LOGF(" %d = %s\n", param_id, value);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceReceiveEvent(SystemServiceEvent* event) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (event == nullptr) {
|
||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
event->event_type = -1;
|
||||
std::memset(event->data, 0, sizeof(event->data));
|
||||
|
||||
return SYSTEM_SERVICE_ERROR_NO_EVENT;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceGetStatus(SystemServiceStatus* status) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (status == nullptr) {
|
||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
*status = SystemServiceStatus();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI
|
||||
SystemServiceGetDisplaySafeAreaInfo(SystemServiceDisplaySafeAreaInfo* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (info == nullptr) {
|
||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
info->ratio = 1.0f;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI
|
||||
SystemServiceGetHdrToneMapLuminance(SystemServiceHdrToneMapLuminance* luminance) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (luminance == nullptr) {
|
||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
luminance->max_full_frame_tone_map_luminance = 80.0f;
|
||||
luminance->max_tone_map_luminance = 1000.0f;
|
||||
luminance->min_tone_map_luminance = 0.0f;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceGetNoticeScreenSkipFlag(bool* value) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (value == nullptr) {
|
||||
return SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
*value = false;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceDisableNoticeScreenSkipFlagAutoSet() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceSetNoticeScreenSkipFlag() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServicePowerTick() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemServiceReportAbnormalTermination(const void* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t info = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(info));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace SystemService
|
||||
|
||||
namespace SystemGesture {
|
||||
|
||||
LIB_VERSION("SystemGesture", 1, "SystemGesture", 1, 1);
|
||||
|
||||
constexpr int SYSTEM_GESTURE_INPUT_TOUCH_PAD = 0;
|
||||
|
||||
constexpr int SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT = -2138505215; /* 0x80890001 */
|
||||
constexpr int SYSTEM_GESTURE_ERROR_EVENT_DATA_NOT_FOUND = -2138505211; /* 0x80890005 */
|
||||
constexpr int SYSTEM_GESTURE_ERROR_INVALID_HANDLE = -2138505210; /* 0x80890006 */
|
||||
|
||||
constexpr int32_t SYSTEM_GESTURE_HANDLE = 1;
|
||||
|
||||
struct SystemGestureVector2 {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
struct SystemGesturePrimitiveTouchEvent {
|
||||
int32_t event_state;
|
||||
uint16_t primitive_id;
|
||||
uint8_t is_updated;
|
||||
uint8_t reserved0;
|
||||
SystemGestureVector2 pressed_position;
|
||||
SystemGestureVector2 current_position;
|
||||
SystemGestureVector2 delta_vector;
|
||||
uint64_t delta_time;
|
||||
uint64_t elapsed_time;
|
||||
uint8_t reserve[32];
|
||||
};
|
||||
|
||||
struct SystemGestureRectangle {
|
||||
float x;
|
||||
float y;
|
||||
float width;
|
||||
float height;
|
||||
uint8_t reserve[8];
|
||||
};
|
||||
|
||||
struct SystemGestureTouchRecognizer {
|
||||
uint64_t reserve[361];
|
||||
};
|
||||
|
||||
struct SystemGestureTouchRecognizerInformation {
|
||||
int32_t gesture_type;
|
||||
SystemGestureRectangle rectangle;
|
||||
uint64_t updated_time;
|
||||
uint8_t reserve[256];
|
||||
};
|
||||
|
||||
struct SystemGestureTouchEvent {
|
||||
uint8_t reserve[168];
|
||||
};
|
||||
|
||||
static bool SystemGestureIsValidHandle(int32_t gesture_handle) {
|
||||
return gesture_handle == SYSTEM_GESTURE_HANDLE;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureInitializePrimitiveTouchRecognizer(const void*) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureFinalizePrimitiveTouchRecognizer() {
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI SystemGestureOpen(int32_t input_type, const void*) {
|
||||
if (input_type != SYSTEM_GESTURE_INPUT_TOUCH_PAD) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return SYSTEM_GESTURE_HANDLE;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureClose(int32_t gesture_handle) {
|
||||
return SystemGestureIsValidHandle(gesture_handle) ? OK : SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureResetPrimitiveTouchRecognizer(int32_t gesture_handle) {
|
||||
return SystemGestureIsValidHandle(gesture_handle) ? OK : SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureUpdatePrimitiveTouchRecognizer(int32_t gesture_handle,
|
||||
const void*) {
|
||||
return SystemGestureIsValidHandle(gesture_handle) ? OK : SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetPrimitiveTouchEvents(
|
||||
int32_t gesture_handle, SystemGesturePrimitiveTouchEvent* event_buffer,
|
||||
uint32_t capacity_of_buffer, uint32_t* number_of_event) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (number_of_event == nullptr) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*number_of_event = 0;
|
||||
if (event_buffer != nullptr && capacity_of_buffer != 0) {
|
||||
std::memset(event_buffer, 0, sizeof(SystemGesturePrimitiveTouchEvent));
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetPrimitiveTouchEventsCount(int32_t gesture_handle) {
|
||||
return SystemGestureIsValidHandle(gesture_handle) ? 0 : SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetPrimitiveTouchEventByIndex(
|
||||
int32_t gesture_handle, uint32_t, SystemGesturePrimitiveTouchEvent* event) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (event != nullptr) {
|
||||
std::memset(event, 0, sizeof(SystemGesturePrimitiveTouchEvent));
|
||||
}
|
||||
return SYSTEM_GESTURE_ERROR_EVENT_DATA_NOT_FOUND;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetPrimitiveTouchEventByPrimitiveID(
|
||||
int32_t gesture_handle, uint16_t, SystemGesturePrimitiveTouchEvent* event) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (event != nullptr) {
|
||||
std::memset(event, 0, sizeof(SystemGesturePrimitiveTouchEvent));
|
||||
}
|
||||
return SYSTEM_GESTURE_ERROR_EVENT_DATA_NOT_FOUND;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI
|
||||
SystemGestureCreateTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer,
|
||||
int32_t, const SystemGestureRectangle*, const void*) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (recognizer == nullptr) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
std::memset(recognizer, 0, sizeof(SystemGestureTouchRecognizer));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureAppendTouchRecognizer(
|
||||
int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
return (recognizer != nullptr ? OK : SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureRemoveTouchRecognizer(
|
||||
int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
return (recognizer != nullptr ? OK : SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureResetTouchRecognizer(
|
||||
int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (recognizer != nullptr) {
|
||||
std::memset(recognizer, 0, sizeof(SystemGestureTouchRecognizer));
|
||||
}
|
||||
return (recognizer != nullptr ? OK : SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetTouchRecognizerInformation(
|
||||
int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer,
|
||||
SystemGestureTouchRecognizerInformation* information) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (recognizer == nullptr || information == nullptr) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
std::memset(information, 0, sizeof(SystemGestureTouchRecognizerInformation));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureUpdateTouchRecognizer(
|
||||
int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
return (recognizer != nullptr ? OK : SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureUpdateAllTouchRecognizer(int32_t gesture_handle) {
|
||||
return SystemGestureIsValidHandle(gesture_handle) ? OK : SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureUpdateTouchRecognizerRectangle(
|
||||
int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer,
|
||||
const SystemGestureRectangle* rectangle) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (recognizer == nullptr || rectangle == nullptr) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetTouchEvents(int32_t gesture_handle,
|
||||
const SystemGestureTouchRecognizer* recognizer,
|
||||
SystemGestureTouchEvent* event_buffer,
|
||||
uint32_t capacity_of_buffer,
|
||||
uint32_t* number_of_event) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (recognizer == nullptr || number_of_event == nullptr) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*number_of_event = 0;
|
||||
if (event_buffer != nullptr && capacity_of_buffer != 0) {
|
||||
std::memset(event_buffer, 0, sizeof(SystemGestureTouchEvent));
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetTouchEventsCount(
|
||||
int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
return (recognizer != nullptr ? 0 : SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetTouchEventByIndex(
|
||||
int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, uint32_t,
|
||||
SystemGestureTouchEvent* event) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (recognizer == nullptr) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (event != nullptr) {
|
||||
std::memset(event, 0, sizeof(SystemGestureTouchEvent));
|
||||
}
|
||||
return SYSTEM_GESTURE_ERROR_EVENT_DATA_NOT_FOUND;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI SystemGestureGetTouchEventByEventID(
|
||||
int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, uint32_t,
|
||||
SystemGestureTouchEvent* event) {
|
||||
if (!SystemGestureIsValidHandle(gesture_handle)) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (recognizer == nullptr) {
|
||||
return SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (event != nullptr) {
|
||||
std::memset(event, 0, sizeof(SystemGestureTouchEvent));
|
||||
}
|
||||
return SYSTEM_GESTURE_ERROR_EVENT_DATA_NOT_FOUND;
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitSystemGesture_1) {
|
||||
LIB_FUNC("qpo-mEOwje0", SystemGesture::SystemGestureOpen);
|
||||
LIB_FUNC("j4yXIA2jJ68", SystemGesture::SystemGestureClose);
|
||||
LIB_FUNC("3pcAvmwKCvM", SystemGesture::SystemGestureInitializePrimitiveTouchRecognizer);
|
||||
LIB_FUNC("3QYCmMlOlCY", SystemGesture::SystemGestureFinalizePrimitiveTouchRecognizer);
|
||||
LIB_FUNC("o11J529VaAE", SystemGesture::SystemGestureResetPrimitiveTouchRecognizer);
|
||||
LIB_FUNC("GgFMb22sbbI", SystemGesture::SystemGestureUpdatePrimitiveTouchRecognizer);
|
||||
LIB_FUNC("L8YmemOeSNY", SystemGesture::SystemGestureGetPrimitiveTouchEvents);
|
||||
LIB_FUNC("JhwByySf9FY", SystemGesture::SystemGestureGetPrimitiveTouchEventsCount);
|
||||
LIB_FUNC("KAeP0+cQPVU", SystemGesture::SystemGestureGetPrimitiveTouchEventByIndex);
|
||||
LIB_FUNC("yBaQ0h9m1NM", SystemGesture::SystemGestureGetPrimitiveTouchEventByPrimitiveID);
|
||||
LIB_FUNC("FWF8zkhr854", SystemGesture::SystemGestureCreateTouchRecognizer);
|
||||
LIB_FUNC("1MMK0W-kMgA", SystemGesture::SystemGestureAppendTouchRecognizer);
|
||||
LIB_FUNC("ELvBVG-LKT0", SystemGesture::SystemGestureRemoveTouchRecognizer);
|
||||
LIB_FUNC("oBuH3zFWYIg", SystemGesture::SystemGestureResetTouchRecognizer);
|
||||
LIB_FUNC("0KrW5eMnrwY", SystemGesture::SystemGestureGetTouchRecognizerInformation);
|
||||
LIB_FUNC("j4h82CQWENo", SystemGesture::SystemGestureUpdateTouchRecognizer);
|
||||
LIB_FUNC("wPJGwI2RM2I", SystemGesture::SystemGestureUpdateAllTouchRecognizer);
|
||||
LIB_FUNC("4WOA1eTx3V8", SystemGesture::SystemGestureUpdateTouchRecognizerRectangle);
|
||||
LIB_FUNC("fLTseA7XiWY", SystemGesture::SystemGestureGetTouchEvents);
|
||||
LIB_FUNC("h8uongcBNVs", SystemGesture::SystemGestureGetTouchEventsCount);
|
||||
LIB_FUNC("TSKvgSz5ChU", SystemGesture::SystemGestureGetTouchEventByIndex);
|
||||
LIB_FUNC("lpsXm7tzeoc", SystemGesture::SystemGestureGetTouchEventByEventID);
|
||||
}
|
||||
|
||||
} // namespace SystemGesture
|
||||
|
||||
LIB_DEFINE(InitSystemService_1) {
|
||||
LIB_FUNC("Vo5V8KAwCmk", SystemService::SystemServiceHideSplashScreen);
|
||||
LIB_FUNC("fZo48un7LK4", SystemService::SystemServiceParamGetInt);
|
||||
LIB_FUNC("SsC-m-S9JTA", SystemService::SystemServiceParamGetString);
|
||||
LIB_FUNC("656LMQSrg6U", SystemService::SystemServiceReceiveEvent);
|
||||
LIB_FUNC("rPo6tV8D9bM", SystemService::SystemServiceGetStatus);
|
||||
LIB_FUNC("1n37q1Bvc5Y", SystemService::SystemServiceGetDisplaySafeAreaInfo);
|
||||
LIB_FUNC("mPpPxv5CZt4", SystemService::SystemServiceGetHdrToneMapLuminance);
|
||||
LIB_FUNC("3RQ5aQfnstU", SystemService::SystemServiceGetNoticeScreenSkipFlag);
|
||||
LIB_FUNC("8Lo6Zv94aho", SystemService::SystemServiceDisableNoticeScreenSkipFlagAutoSet);
|
||||
LIB_FUNC("Q3utJvma4Mo", SystemService::SystemServiceSetNoticeScreenSkipFlag);
|
||||
LIB_FUNC("XbbJC3E+L5M", SystemService::SystemServicePowerTick);
|
||||
LIB_FUNC("3s8cHiCBKBE", SystemService::SystemServiceReportAbnormalTermination);
|
||||
SystemGesture::InitSystemGesture_1(s);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,566 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "kernel/pthread.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibUlt {
|
||||
|
||||
LIB_VERSION("Ult", 1, "Ult", 1, 1);
|
||||
|
||||
constexpr int ULT_ERROR_NULL = -2139029503; // 0x80810001
|
||||
constexpr int ULT_ERROR_INVALID = -2139029500; // 0x80810004
|
||||
constexpr int ULT_ERROR_STATE = -2139029498; // 0x80810006
|
||||
constexpr int ULT_ERROR_AGAIN = -2139029496; // 0x80810008
|
||||
|
||||
struct UltMutexOptParam {
|
||||
uint32_t reserved_header[2];
|
||||
uint32_t attribute;
|
||||
uint32_t reserved0;
|
||||
};
|
||||
|
||||
struct UltUlthreadRuntimeOptParam {
|
||||
uint8_t bytes[128];
|
||||
};
|
||||
|
||||
struct UltMutexState {
|
||||
std::recursive_mutex mutex;
|
||||
uint32_t attribute = 0;
|
||||
};
|
||||
|
||||
struct UltResourcePoolState {
|
||||
uint32_t num_threads = 0;
|
||||
uint32_t num_sync_objects = 0;
|
||||
void* work_area = nullptr;
|
||||
};
|
||||
|
||||
struct UltQueueDataResourcePoolState {
|
||||
uint32_t num_data = 0;
|
||||
uint64_t data_size = 0;
|
||||
uint32_t num_queue_object = 0;
|
||||
void* waiting_pool = nullptr;
|
||||
void* work_area = nullptr;
|
||||
};
|
||||
|
||||
struct UltQueueState {
|
||||
std::mutex mutex;
|
||||
std::deque<std::vector<uint8_t>> items;
|
||||
uint64_t data_size = 0;
|
||||
uint32_t capacity = 0;
|
||||
void* waiting_pool = nullptr;
|
||||
void* data_pool = nullptr;
|
||||
};
|
||||
|
||||
struct UltRuntimeState {
|
||||
uint32_t max_num_ulthread = 0;
|
||||
uint32_t num_worker_thread = 0;
|
||||
void* work_area = nullptr;
|
||||
};
|
||||
|
||||
using UltUlthreadEntry = KYTY_SYSV_ABI int32_t (*)(uint64_t);
|
||||
|
||||
struct UltUlthreadState {
|
||||
UltUlthreadEntry entry = nullptr;
|
||||
uint64_t arg = 0;
|
||||
LibKernel::Pthread thread = nullptr;
|
||||
};
|
||||
|
||||
static std::mutex g_ult_mutex;
|
||||
static std::unordered_map<void*, std::shared_ptr<UltMutexState>> g_ult_mutexes;
|
||||
static std::unordered_map<void*, UltResourcePoolState> g_ult_resource_pools;
|
||||
static std::unordered_map<void*, UltQueueDataResourcePoolState> g_ult_queue_data_pools;
|
||||
static std::unordered_map<void*, std::shared_ptr<UltQueueState>> g_ult_queues;
|
||||
static std::unordered_map<void*, UltRuntimeState> g_ult_runtimes;
|
||||
static std::unordered_map<void*, std::shared_ptr<UltUlthreadState>> g_ult_ulthreads;
|
||||
|
||||
static uint64_t ult_align_up(uint64_t value, uint64_t alignment) {
|
||||
return (value + alignment - 1u) & ~(alignment - 1u);
|
||||
}
|
||||
|
||||
static int UltQueueGetState(void* queue, std::shared_ptr<UltQueueState>* state) {
|
||||
EXIT_IF(state == nullptr);
|
||||
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
auto it = g_ult_queues.find(queue);
|
||||
if (it == g_ult_queues.end()) {
|
||||
return (queue == nullptr ? ULT_ERROR_NULL : ULT_ERROR_STATE);
|
||||
}
|
||||
|
||||
*state = it->second;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltInitialize() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltFinalize() {
|
||||
PRINT_NAME();
|
||||
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
g_ult_mutexes.clear();
|
||||
g_ult_resource_pools.clear();
|
||||
g_ult_queue_data_pools.clear();
|
||||
g_ult_queues.clear();
|
||||
g_ult_runtimes.clear();
|
||||
g_ult_ulthreads.clear();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltUlthreadRuntimeOptParamInitialize(UltUlthreadRuntimeOptParam* opt_param,
|
||||
uint32_t build_version) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (opt_param == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
LOGF("\t opt_param = 0x%016" PRIx64 "\n"
|
||||
"\t build_version = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(opt_param), build_version);
|
||||
|
||||
std::memset(opt_param, 0, sizeof(*opt_param));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static uint64_t KYTY_SYSV_ABI UltUlthreadRuntimeGetWorkAreaSize(uint32_t max_num_ulthread,
|
||||
uint32_t num_worker_thread) {
|
||||
PRINT_NAME();
|
||||
|
||||
return ult_align_up(static_cast<uint64_t>(max_num_ulthread) * 256u +
|
||||
static_cast<uint64_t>(num_worker_thread) * 16u * 1024u,
|
||||
8u);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltUlthreadRuntimeCreate(void* runtime, const char* name,
|
||||
uint32_t max_num_ulthread,
|
||||
uint32_t num_worker_thread, void* work_area,
|
||||
const void* opt_param, uint32_t build_version) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (runtime == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
LOGF("\t runtime = 0x%016" PRIx64 "\n"
|
||||
"\t name = 0x%016" PRIx64 "\n"
|
||||
"\t max_num_ulthread = %" PRIu32 "\n"
|
||||
"\t num_worker_thread = %" PRIu32 "\n"
|
||||
"\t work_area = 0x%016" PRIx64 "\n"
|
||||
"\t opt_param = 0x%016" PRIx64 "\n"
|
||||
"\t build_version = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(runtime), reinterpret_cast<uint64_t>(name), max_num_ulthread,
|
||||
num_worker_thread, reinterpret_cast<uint64_t>(work_area),
|
||||
reinterpret_cast<uint64_t>(opt_param), build_version);
|
||||
|
||||
std::memset(runtime, 0, 4096);
|
||||
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
g_ult_runtimes[runtime] = {max_num_ulthread, num_worker_thread, work_area};
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI void* UltUlthreadRun(void* arg) {
|
||||
auto* state = static_cast<UltUlthreadState*>(arg);
|
||||
return reinterpret_cast<void*>(static_cast<intptr_t>(state->entry(state->arg)));
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltUlthreadCreate(void* ulthread, const char* name, UltUlthreadEntry entry,
|
||||
uint64_t arg, void* context, uint64_t size_context,
|
||||
void* runtime, const void* opt_param,
|
||||
uint32_t build_version) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t ulthread = 0x%016" PRIx64 "\n"
|
||||
"\t name = 0x%016" PRIx64 "\n"
|
||||
"\t entry = 0x%016" PRIx64 "\n"
|
||||
"\t arg = 0x%016" PRIx64 "\n"
|
||||
"\t context = 0x%016" PRIx64 "\n"
|
||||
"\t size_context = 0x%016" PRIx64 "\n"
|
||||
"\t runtime = 0x%016" PRIx64 "\n"
|
||||
"\t opt_param = 0x%016" PRIx64 "\n"
|
||||
"\t build_version = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(ulthread), reinterpret_cast<uint64_t>(name),
|
||||
reinterpret_cast<uint64_t>(entry), arg, reinterpret_cast<uint64_t>(context), size_context,
|
||||
reinterpret_cast<uint64_t>(runtime), reinterpret_cast<uint64_t>(opt_param), build_version);
|
||||
|
||||
if (ulthread == nullptr || entry == nullptr || context == nullptr || runtime == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
auto state = std::make_shared<UltUlthreadState>();
|
||||
state->entry = entry;
|
||||
state->arg = arg;
|
||||
|
||||
{
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
if (g_ult_runtimes.find(runtime) == g_ult_runtimes.end()) {
|
||||
return ULT_ERROR_STATE;
|
||||
}
|
||||
if (g_ult_ulthreads.find(ulthread) != g_ult_ulthreads.end()) {
|
||||
return ULT_ERROR_STATE;
|
||||
}
|
||||
std::memset(ulthread, 0, 512);
|
||||
g_ult_ulthreads[ulthread] = state;
|
||||
}
|
||||
|
||||
const auto result = LibKernel::PthreadCreate(&state->thread, nullptr, UltUlthreadRun,
|
||||
state.get(), name != nullptr ? name : "");
|
||||
if (result != OK) {
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
g_ult_ulthreads.erase(ulthread);
|
||||
return ULT_ERROR_AGAIN;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltUlthreadJoin(void* ulthread, int32_t* status) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t ulthread = 0x%016" PRIx64 "\n"
|
||||
"\t status = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(ulthread), reinterpret_cast<uint64_t>(status));
|
||||
|
||||
if (ulthread == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
std::shared_ptr<UltUlthreadState> state;
|
||||
{
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
auto it = g_ult_ulthreads.find(ulthread);
|
||||
if (it == g_ult_ulthreads.end()) {
|
||||
return ULT_ERROR_STATE;
|
||||
}
|
||||
state = it->second;
|
||||
}
|
||||
|
||||
void* result = nullptr;
|
||||
if (LibKernel::PthreadJoin(state->thread, &result) != OK) {
|
||||
return ULT_ERROR_STATE;
|
||||
}
|
||||
if (status != nullptr) {
|
||||
*status = static_cast<int32_t>(reinterpret_cast<intptr_t>(result));
|
||||
}
|
||||
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
g_ult_ulthreads.erase(ulthread);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static uint64_t KYTY_SYSV_ABI
|
||||
UltWaitingQueueResourcePoolGetWorkAreaSize(uint32_t num_threads, uint32_t num_sync_objects) {
|
||||
PRINT_NAME();
|
||||
|
||||
return ult_align_up(static_cast<uint64_t>(num_threads + num_sync_objects) * 256u, 8u);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltWaitingQueueResourcePoolCreate(void* pool, const char* name,
|
||||
uint32_t num_threads,
|
||||
uint32_t num_sync_objects,
|
||||
void* work_area, const void* opt_param,
|
||||
uint32_t build_version) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (pool == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
LOGF("\t pool = 0x%016" PRIx64 "\n"
|
||||
"\t name = 0x%016" PRIx64 "\n"
|
||||
"\t num_threads = %" PRIu32 "\n"
|
||||
"\t num_sync_objects = %" PRIu32 "\n"
|
||||
"\t work_area = 0x%016" PRIx64 "\n"
|
||||
"\t opt_param = 0x%016" PRIx64 "\n"
|
||||
"\t build_version = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(pool), reinterpret_cast<uint64_t>(name), num_threads,
|
||||
num_sync_objects, reinterpret_cast<uint64_t>(work_area),
|
||||
reinterpret_cast<uint64_t>(opt_param), build_version);
|
||||
|
||||
std::memset(pool, 0, 256);
|
||||
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
g_ult_resource_pools[pool] = {num_threads, num_sync_objects, work_area};
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static uint64_t KYTY_SYSV_ABI UltQueueDataResourcePoolGetWorkAreaSize(uint32_t num_data,
|
||||
uint64_t data_size,
|
||||
uint32_t num_queue_object) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t num_data = %" PRIu32 "\n"
|
||||
"\t data_size = 0x%016" PRIx64 "\n"
|
||||
"\t num_queue_object = %" PRIu32 "\n",
|
||||
num_data, data_size, num_queue_object);
|
||||
|
||||
const uint64_t data_area = static_cast<uint64_t>(num_data) * ult_align_up(data_size, 8u);
|
||||
const uint64_t queue_area = static_cast<uint64_t>(num_queue_object) * 512u;
|
||||
|
||||
return ult_align_up(data_area + queue_area, 8u);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltQueueDataResourcePoolCreate(void* pool, const char* name,
|
||||
uint32_t num_data, uint64_t data_size,
|
||||
uint32_t num_queue_object,
|
||||
void* waiting_queue_resource_pool,
|
||||
void* work_area, const void* opt_param,
|
||||
uint32_t build_version) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (pool == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
LOGF("\t pool = 0x%016" PRIx64 "\n"
|
||||
"\t name = 0x%016" PRIx64 "\n"
|
||||
"\t num_data = %" PRIu32 "\n"
|
||||
"\t data_size = 0x%016" PRIx64 "\n"
|
||||
"\t num_queue_object = %" PRIu32 "\n"
|
||||
"\t waiting_queue_resource_pool = 0x%016" PRIx64 "\n"
|
||||
"\t work_area = 0x%016" PRIx64 "\n"
|
||||
"\t opt_param = 0x%016" PRIx64 "\n"
|
||||
"\t build_version = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(pool), reinterpret_cast<uint64_t>(name), num_data, data_size,
|
||||
num_queue_object, reinterpret_cast<uint64_t>(waiting_queue_resource_pool),
|
||||
reinterpret_cast<uint64_t>(work_area), reinterpret_cast<uint64_t>(opt_param),
|
||||
build_version);
|
||||
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
if (waiting_queue_resource_pool != nullptr &&
|
||||
g_ult_resource_pools.find(waiting_queue_resource_pool) == g_ult_resource_pools.end()) {
|
||||
return ULT_ERROR_INVALID;
|
||||
}
|
||||
|
||||
std::memset(pool, 0, 512);
|
||||
g_ult_queue_data_pools[pool] = {num_data, data_size, num_queue_object,
|
||||
waiting_queue_resource_pool, work_area};
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltQueueCreate(void* queue, const char* name, uint64_t data_size,
|
||||
void* waiting_queue_resource_pool,
|
||||
void* queue_data_resource_pool, const void* opt_param,
|
||||
uint32_t build_version) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (queue == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
LOGF("\t queue = 0x%016" PRIx64 "\n"
|
||||
"\t name = 0x%016" PRIx64 "\n"
|
||||
"\t data_size = 0x%016" PRIx64 "\n"
|
||||
"\t waiting_queue_resource_pool = 0x%016" PRIx64 "\n"
|
||||
"\t queue_data_resource_pool = 0x%016" PRIx64 "\n"
|
||||
"\t opt_param = 0x%016" PRIx64 "\n"
|
||||
"\t build_version = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(queue), reinterpret_cast<uint64_t>(name), data_size,
|
||||
reinterpret_cast<uint64_t>(waiting_queue_resource_pool),
|
||||
reinterpret_cast<uint64_t>(queue_data_resource_pool),
|
||||
reinterpret_cast<uint64_t>(opt_param), build_version);
|
||||
|
||||
auto state = std::make_shared<UltQueueState>();
|
||||
state->data_size = data_size;
|
||||
state->waiting_pool = waiting_queue_resource_pool;
|
||||
state->data_pool = queue_data_resource_pool;
|
||||
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
auto data_pool = g_ult_queue_data_pools.find(queue_data_resource_pool);
|
||||
if (data_pool == g_ult_queue_data_pools.end() ||
|
||||
(waiting_queue_resource_pool != nullptr &&
|
||||
g_ult_resource_pools.find(waiting_queue_resource_pool) == g_ult_resource_pools.end())) {
|
||||
return ULT_ERROR_INVALID;
|
||||
}
|
||||
state->capacity = data_pool->second.num_data;
|
||||
|
||||
std::memset(queue, 0, 512);
|
||||
g_ult_queues[queue] = std::move(state);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltQueuePush(void* queue, const void* data) {
|
||||
PRINT_NAME();
|
||||
|
||||
std::shared_ptr<UltQueueState> state;
|
||||
if (auto ret = UltQueueGetState(queue, &state); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (data == nullptr && state->data_size != 0) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
std::scoped_lock lock(state->mutex);
|
||||
if (state->capacity != 0 && state->items.size() >= state->capacity) {
|
||||
static std::atomic<uint32_t> log_count {0};
|
||||
if (log_count.fetch_add(1) < 32) {
|
||||
LOGF("\t queue full, dropping pushed item: queue=0x%016" PRIx64 " capacity=%" PRIu32
|
||||
" data_size=0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(queue), state->capacity, state->data_size);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
auto& item = state->items.emplace_back(static_cast<size_t>(state->data_size));
|
||||
if (!item.empty()) {
|
||||
std::memcpy(item.data(), data, item.size());
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltQueueTryPop(void* queue, void* data) {
|
||||
PRINT_NAME();
|
||||
|
||||
std::shared_ptr<UltQueueState> state;
|
||||
if (auto ret = UltQueueGetState(queue, &state); ret != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (data == nullptr && state->data_size != 0) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
std::scoped_lock lock(state->mutex);
|
||||
if (state->items.empty()) {
|
||||
return ULT_ERROR_AGAIN;
|
||||
}
|
||||
|
||||
auto item = std::move(state->items.front());
|
||||
state->items.pop_front();
|
||||
if (!item.empty()) {
|
||||
std::memcpy(data, item.data(), item.size());
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltMutexOptParamInitialize(UltMutexOptParam* opt_param,
|
||||
uint32_t build_version) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (opt_param == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
LOGF("\t opt_param = 0x%016" PRIx64 "\n"
|
||||
"\t build_version = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(opt_param), build_version);
|
||||
|
||||
std::memset(opt_param, 0, sizeof(*opt_param));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltMutexCreate(void* mutex, const char* name,
|
||||
void* waiting_queue_resource_pool,
|
||||
const UltMutexOptParam* opt_param, uint32_t build_version) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (mutex == nullptr) {
|
||||
return ULT_ERROR_NULL;
|
||||
}
|
||||
|
||||
auto state = std::make_shared<UltMutexState>();
|
||||
state->attribute = (opt_param != nullptr ? opt_param->attribute : 0);
|
||||
|
||||
LOGF("\t mutex = 0x%016" PRIx64 "\n"
|
||||
"\t name = 0x%016" PRIx64 "\n"
|
||||
"\t waiting_queue_resource_pool = 0x%016" PRIx64 "\n"
|
||||
"\t attribute = 0x%08" PRIx32 "\n"
|
||||
"\t build_version = 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(mutex), reinterpret_cast<uint64_t>(name),
|
||||
reinterpret_cast<uint64_t>(waiting_queue_resource_pool), state->attribute, build_version);
|
||||
|
||||
std::memset(mutex, 0, 256);
|
||||
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
if (waiting_queue_resource_pool != nullptr &&
|
||||
g_ult_resource_pools.find(waiting_queue_resource_pool) == g_ult_resource_pools.end()) {
|
||||
return ULT_ERROR_INVALID;
|
||||
}
|
||||
g_ult_mutexes[mutex] = state;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltMutexLock(void* mutex) {
|
||||
PRINT_NAME();
|
||||
|
||||
std::shared_ptr<UltMutexState> state;
|
||||
{
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
auto it = g_ult_mutexes.find(mutex);
|
||||
if (it == g_ult_mutexes.end()) {
|
||||
return (mutex == nullptr ? ULT_ERROR_NULL : ULT_ERROR_STATE);
|
||||
}
|
||||
state = it->second;
|
||||
}
|
||||
|
||||
state->mutex.lock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI UltMutexUnlock(void* mutex) {
|
||||
PRINT_NAME();
|
||||
|
||||
std::shared_ptr<UltMutexState> state;
|
||||
{
|
||||
std::scoped_lock lock(g_ult_mutex);
|
||||
auto it = g_ult_mutexes.find(mutex);
|
||||
if (it == g_ult_mutexes.end()) {
|
||||
return (mutex == nullptr ? ULT_ERROR_NULL : ULT_ERROR_STATE);
|
||||
}
|
||||
state = it->second;
|
||||
}
|
||||
|
||||
state->mutex.unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitUlt_1) {
|
||||
LIB_FUNC("hZIg1EWGsHM", UltInitialize);
|
||||
LIB_FUNC("d-kSG2fLrvI", UltFinalize);
|
||||
LIB_FUNC("V2u3WLrwh64", UltUlthreadRuntimeOptParamInitialize);
|
||||
LIB_FUNC("grs2pbc2awM", UltUlthreadRuntimeGetWorkAreaSize);
|
||||
LIB_FUNC("jw9FkZBXo-g", UltUlthreadRuntimeCreate);
|
||||
LIB_FUNC("znI3q8S7KQ4", UltUlthreadCreate);
|
||||
LIB_FUNC("gCeAI57LGgI", UltUlthreadJoin);
|
||||
LIB_FUNC("WIWV1Qd7PFU", UltWaitingQueueResourcePoolGetWorkAreaSize);
|
||||
LIB_FUNC("YiHujOG9vXY", UltWaitingQueueResourcePoolCreate);
|
||||
LIB_FUNC("evj9YPkS8s4", UltQueueDataResourcePoolGetWorkAreaSize);
|
||||
LIB_FUNC("TFHm6-N6vks", UltQueueDataResourcePoolCreate);
|
||||
LIB_FUNC("9Y5keOvb6ok", UltQueueCreate);
|
||||
LIB_FUNC("dUwpX3e5NDE", UltQueuePush);
|
||||
LIB_FUNC("uZz3ci7XYqc", UltQueueTryPop);
|
||||
LIB_FUNC("1+8t9aHLiz8", UltMutexOptParamInitialize);
|
||||
LIB_FUNC("mmt8Sa6tL6c", UltMutexCreate);
|
||||
LIB_FUNC("8hEGkR1pfr8", UltMutexLock);
|
||||
LIB_FUNC("h0XebKiMBtk", UltMutexUnlock);
|
||||
}
|
||||
|
||||
} // namespace LibUlt
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,279 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("UserService", 1, "UserService", 1, 1);
|
||||
|
||||
namespace UserService {
|
||||
|
||||
struct UserServiceLoginUserIdList {
|
||||
int user_id[4];
|
||||
};
|
||||
|
||||
enum UserServiceEventType { UserServiceEventTypeLogin, UserServiceEventTypeLogout };
|
||||
|
||||
struct SceUserServiceEvent {
|
||||
UserServiceEventType event_type;
|
||||
int user_id;
|
||||
};
|
||||
|
||||
struct UserServiceGamePresets {
|
||||
size_t this_size;
|
||||
uint32_t difficulty;
|
||||
uint32_t priority;
|
||||
uint32_t invert_vertical_view_for_1st_person_view;
|
||||
uint32_t invert_horizontal_view_for_1st_person_view;
|
||||
uint32_t invert_vertical_view_for_3rd_person_view;
|
||||
uint32_t invert_horizontal_view_for_3rd_person_view;
|
||||
uint32_t display_sub_titles;
|
||||
uint32_t audio_language;
|
||||
};
|
||||
|
||||
static_assert(sizeof(UserServiceGamePresets) == 40);
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceInitialize(const void* /*params*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceInitialize2() {
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetInitialUser(int* user_id) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(user_id == nullptr);
|
||||
|
||||
*user_id = 1000;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetEvent(SceUserServiceEvent* event) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(event == nullptr);
|
||||
|
||||
static bool logged_in = false;
|
||||
|
||||
if (!logged_in) {
|
||||
logged_in = true;
|
||||
event->event_type = UserServiceEventTypeLogin;
|
||||
event->user_id = 1000;
|
||||
return OK;
|
||||
}
|
||||
|
||||
return USER_SERVICE_ERROR_NO_EVENT;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetLoginUserIdList(UserServiceLoginUserIdList* user_id_list) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(user_id_list == nullptr);
|
||||
|
||||
user_id_list->user_id[0] = 1000;
|
||||
user_id_list->user_id[1] = -1;
|
||||
user_id_list->user_id[2] = -1;
|
||||
user_id_list->user_id[3] = -1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetUserName(int user_id, char* name, size_t size) {
|
||||
EXIT_NOT_IMPLEMENTED(user_id != 1000);
|
||||
EXIT_NOT_IMPLEMENTED(size < 5);
|
||||
|
||||
int s = snprintf(name, size, "%s", "Kyty");
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(static_cast<size_t>(s) >= size);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetUserNumber(int user_id, int32_t* number) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (number == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
*number = 1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetGamePresets(int user_id, UserServiceGamePresets* presets) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (presets == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
auto this_size = presets->this_size;
|
||||
if (this_size == 0 || this_size > sizeof(UserServiceGamePresets)) {
|
||||
this_size = sizeof(UserServiceGamePresets);
|
||||
}
|
||||
|
||||
std::memset(presets, 0, this_size);
|
||||
presets->this_size = sizeof(UserServiceGamePresets);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetAccessibilityVibration(int user_id, int32_t* vibration) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (vibration == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
*vibration = 1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetAccessibilityTriggerEffect(int user_id,
|
||||
int32_t* trigger_effect) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (trigger_effect == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
*trigger_effect = 1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetAgeLevel(int user_id, uint32_t* age_level) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (age_level == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
*age_level = 9;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetAccessibilityChatTranscription(int user_id,
|
||||
int32_t* chat_transcription) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (chat_transcription == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
*chat_transcription = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int
|
||||
UserServiceGetAccessibilityPressAndHoldDelay(int user_id, int32_t* press_and_hold_delay) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (press_and_hold_delay == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
*press_and_hold_delay = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetAccessibilityZoomEnabled(int user_id,
|
||||
int32_t* zoom_enabled) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (zoom_enabled == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
*zoom_enabled = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetAccessibilityZoomFollowFocus(int user_id,
|
||||
int32_t* zoom_follow_focus) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (zoom_follow_focus == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
*zoom_follow_focus = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServicePlatformPrivacyWs1Stub(uint64_t, uint64_t, uint64_t, uint64_t,
|
||||
uint64_t, uint64_t) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace UserService
|
||||
|
||||
LIB_DEFINE(InitUserService_1) {
|
||||
LIB_FUNC("j3YMu1MVNNo", UserService::UserServiceInitialize);
|
||||
LIB_FUNC("az-0R6eviZ0", UserService::UserServiceInitialize2);
|
||||
LIB_FUNC("CdWp0oHWGr0", UserService::UserServiceGetInitialUser);
|
||||
LIB_FUNC("yH17Q6NWtVg", UserService::UserServiceGetEvent);
|
||||
LIB_FUNC("fPhymKNvK-A", UserService::UserServiceGetLoginUserIdList);
|
||||
LIB_FUNC("1xxcMiGu2fo", UserService::UserServiceGetUserName);
|
||||
LIB_FUNC("bwFjS+bX9mA", UserService::UserServiceGetUserNumber);
|
||||
LIB_FUNC("qbwy0Ub8b3M", UserService::UserServiceGetUserNumber);
|
||||
LIB_FUNC("-sD02mFDBh4", UserService::UserServiceGetGamePresets);
|
||||
LIB_FUNC("woNpu+45RLk", UserService::UserServiceGetAgeLevel);
|
||||
LIB_FUNC("rnEhHqG-4xo", UserService::UserServiceGetAccessibilityChatTranscription);
|
||||
LIB_FUNC("ZKJtxdgvzwg", UserService::UserServiceGetAccessibilityPressAndHoldDelay);
|
||||
LIB_FUNC("qWYHOFwqCxY", UserService::UserServiceGetAccessibilityVibration);
|
||||
LIB_FUNC("-3Y5GO+-i78", UserService::UserServiceGetAccessibilityTriggerEffect);
|
||||
LIB_FUNC("hD-H81EN9Vg", UserService::UserServiceGetAccessibilityZoomEnabled);
|
||||
LIB_FUNC("O6IW1-Dwm-w", UserService::UserServiceGetAccessibilityZoomFollowFocus);
|
||||
LIB_FUNC("D-CzAxQL0XI", UserService::UserServicePlatformPrivacyWs1Stub);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,455 @@
|
||||
#include "common/abi.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
LIB_VERSION("Videodec2", 1, "Videodec2", 1, 1);
|
||||
|
||||
namespace VideoDec2 {
|
||||
|
||||
constexpr int32_t VIDEODEC2_ERROR_STRUCT_SIZE = -2128805631; // 0x811d0101
|
||||
constexpr int32_t VIDEODEC2_ERROR_ARGUMENT_POINTER = -2128805630; // 0x811d0102
|
||||
constexpr int32_t VIDEODEC2_ERROR_DECODER_INSTANCE = -2128805629; // 0x811d0103
|
||||
constexpr int32_t VIDEODEC2_ERROR_MEMORY_SIZE = -2128805628; // 0x811d0104
|
||||
constexpr int32_t VIDEODEC2_ERROR_MEMORY_POINTER = -2128805627; // 0x811d0105
|
||||
constexpr int32_t VIDEODEC2_ERROR_FRAME_BUFFER_SIZE = -2128805626; // 0x811d0106
|
||||
constexpr int32_t VIDEODEC2_ERROR_FRAME_BUFFER_POINTER = -2128805625; // 0x811d0107
|
||||
constexpr int32_t VIDEODEC2_ERROR_CONFIG_INFO = -2128805376; // 0x811d0200
|
||||
constexpr int32_t VIDEODEC2_ERROR_COMPUTE_PIPE_ID = -2128805375; // 0x811d0201
|
||||
constexpr int32_t VIDEODEC2_ERROR_COMPUTE_QUEUE_ID = -2128805374; // 0x811d0202
|
||||
constexpr int32_t VIDEODEC2_ERROR_RESOURCE_TYPE = -2128805373; // 0x811d0203
|
||||
constexpr int32_t VIDEODEC2_ERROR_INPUT_QUEUE_DEPTH = -2128805370; // 0x811d0206
|
||||
constexpr int32_t VIDEODEC2_ERROR_DPB_FRAME_COUNT = -2128805367; // 0x811d0209
|
||||
constexpr int32_t VIDEODEC2_ERROR_FRAME_WIDTH_HEIGHT = -2128805366; // 0x811d020a
|
||||
|
||||
constexpr uint32_t VIDEODEC2_RESOURCE_TYPE_COMPUTE = 1;
|
||||
constexpr size_t VIDEODEC2_MIN_MEMORY_SIZE = 16ull * 1024ull * 1024ull;
|
||||
constexpr uint32_t VIDEODEC2_FRAME_FORMAT_DEFAULT = 0;
|
||||
|
||||
using Videodec2Decoder = void*;
|
||||
using Videodec2ComputeQueue = void*;
|
||||
|
||||
struct Videodec2DecoderConfigInfo {
|
||||
size_t this_size;
|
||||
uint32_t resource_type;
|
||||
uint32_t codec_type;
|
||||
uint32_t profile;
|
||||
uint32_t max_level;
|
||||
int32_t max_frame_width;
|
||||
int32_t max_frame_height;
|
||||
int32_t max_dpb_frame_count;
|
||||
uint32_t decode_input_queue_depth;
|
||||
Videodec2ComputeQueue compute_queue;
|
||||
uint64_t cpu_affinity_mask;
|
||||
int32_t cpu_thread_priority;
|
||||
bool optimize_progressive_video;
|
||||
bool check_memory_type;
|
||||
uint8_t reserved0;
|
||||
uint8_t reserved1;
|
||||
void* extra_config_info;
|
||||
};
|
||||
|
||||
struct Videodec2DecoderMemoryInfo {
|
||||
size_t this_size;
|
||||
size_t cpu_memory_size;
|
||||
void* cpu_memory;
|
||||
size_t gpu_memory_size;
|
||||
void* gpu_memory;
|
||||
size_t cpu_gpu_memory_size;
|
||||
void* cpu_gpu_memory;
|
||||
size_t max_frame_buffer_size;
|
||||
uint32_t frame_buffer_alignment;
|
||||
uint32_t reserved0;
|
||||
};
|
||||
|
||||
struct Videodec2InputData {
|
||||
size_t this_size;
|
||||
void* au_data;
|
||||
size_t au_size;
|
||||
uint64_t pts_data;
|
||||
uint64_t dts_data;
|
||||
uint64_t attached_data;
|
||||
};
|
||||
|
||||
struct Videodec2OutputInfo {
|
||||
size_t this_size;
|
||||
bool is_valid;
|
||||
bool is_error_frame;
|
||||
uint8_t picture_count;
|
||||
bool is_discarded_frame;
|
||||
uint32_t codec_type;
|
||||
uint32_t frame_width;
|
||||
uint32_t frame_pitch;
|
||||
uint32_t frame_height;
|
||||
void* frame_buffer;
|
||||
size_t frame_buffer_size;
|
||||
uint32_t frame_format;
|
||||
uint32_t frame_pitch_in_bytes;
|
||||
};
|
||||
|
||||
struct Videodec2FrameBuffer {
|
||||
size_t this_size;
|
||||
void* frame_buffer;
|
||||
size_t frame_buffer_size;
|
||||
bool is_accepted;
|
||||
};
|
||||
|
||||
struct Videodec2ComputeMemoryInfo {
|
||||
size_t this_size;
|
||||
size_t cpu_gpu_memory_size;
|
||||
void* cpu_gpu_memory;
|
||||
};
|
||||
|
||||
struct Videodec2ComputeConfigInfo {
|
||||
size_t this_size;
|
||||
uint16_t compute_pipe_id;
|
||||
uint16_t compute_queue_id;
|
||||
bool check_memory_type;
|
||||
uint8_t reserved0;
|
||||
uint16_t reserved1;
|
||||
};
|
||||
|
||||
struct DecoderState {
|
||||
uint64_t magic;
|
||||
uint32_t codec_type;
|
||||
};
|
||||
|
||||
static_assert(sizeof(Videodec2ComputeMemoryInfo) == 24);
|
||||
static_assert(sizeof(Videodec2ComputeConfigInfo) == 16);
|
||||
static_assert(sizeof(Videodec2DecoderConfigInfo) == 72);
|
||||
static_assert(sizeof(Videodec2DecoderMemoryInfo) == 72);
|
||||
static_assert(sizeof(Videodec2InputData) == 48);
|
||||
static_assert(sizeof(Videodec2OutputInfo) == 56);
|
||||
static_assert(sizeof(Videodec2FrameBuffer) == 32);
|
||||
|
||||
constexpr uint64_t DECODER_MAGIC = 0x4b59545956444543ull; // KYTYVDEC
|
||||
|
||||
static std::mutex g_decoder_mutex;
|
||||
static std::unordered_set<void*> g_decoders;
|
||||
|
||||
static bool IsOutputInfoSizeValid(size_t this_size) {
|
||||
return this_size == sizeof(Videodec2OutputInfo) ||
|
||||
(this_size | 8u) == sizeof(Videodec2OutputInfo);
|
||||
}
|
||||
|
||||
static DecoderState* GetDecoder(Videodec2Decoder decoder) {
|
||||
std::scoped_lock lock(g_decoder_mutex);
|
||||
return g_decoders.contains(decoder) ? static_cast<DecoderState*>(decoder) : nullptr;
|
||||
}
|
||||
|
||||
static void FillNoPictureOutput(const Videodec2FrameBuffer* frame_buffer,
|
||||
Videodec2OutputInfo* output_info, uint32_t codec_type) {
|
||||
output_info->is_valid = false;
|
||||
output_info->is_error_frame = false;
|
||||
output_info->picture_count = 0;
|
||||
output_info->is_discarded_frame = false;
|
||||
output_info->codec_type = codec_type;
|
||||
output_info->frame_width = 0;
|
||||
output_info->frame_pitch = 0;
|
||||
output_info->frame_height = 0;
|
||||
output_info->frame_buffer = frame_buffer != nullptr ? frame_buffer->frame_buffer : nullptr;
|
||||
output_info->frame_buffer_size = frame_buffer != nullptr ? frame_buffer->frame_buffer_size : 0;
|
||||
output_info->frame_format = VIDEODEC2_FRAME_FORMAT_DEFAULT;
|
||||
output_info->frame_pitch_in_bytes = 0;
|
||||
}
|
||||
|
||||
static int32_t ValidateDecoderConfig(const Videodec2DecoderConfigInfo* config) {
|
||||
if (config->resource_type != VIDEODEC2_RESOURCE_TYPE_COMPUTE) {
|
||||
return VIDEODEC2_ERROR_RESOURCE_TYPE;
|
||||
}
|
||||
|
||||
if (config->reserved0 != 0 || config->reserved1 != 0) {
|
||||
return VIDEODEC2_ERROR_CONFIG_INFO;
|
||||
}
|
||||
|
||||
if (config->decode_input_queue_depth == 0) {
|
||||
return VIDEODEC2_ERROR_INPUT_QUEUE_DEPTH;
|
||||
}
|
||||
|
||||
if (config->max_dpb_frame_count < -1 || config->max_dpb_frame_count == 0) {
|
||||
return VIDEODEC2_ERROR_DPB_FRAME_COUNT;
|
||||
}
|
||||
|
||||
if (config->max_frame_width < -1 || config->max_frame_height < -1 ||
|
||||
config->max_frame_width == 0 || config->max_frame_height == 0) {
|
||||
return VIDEODEC2_ERROR_FRAME_WIDTH_HEIGHT;
|
||||
}
|
||||
|
||||
if (config->compute_queue == nullptr) {
|
||||
return VIDEODEC2_ERROR_CONFIG_INFO;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI
|
||||
QueryComputeMemoryInfo(Videodec2ComputeMemoryInfo* compute_memory_info) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (compute_memory_info == nullptr) {
|
||||
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
|
||||
if (compute_memory_info->this_size != sizeof(Videodec2ComputeMemoryInfo)) {
|
||||
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
||||
compute_memory_info->cpu_gpu_memory_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
||||
compute_memory_info->cpu_gpu_memory = nullptr;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI AllocateComputeQueue(
|
||||
const Videodec2ComputeConfigInfo* compute_config_info,
|
||||
const Videodec2ComputeMemoryInfo* compute_memory_info, Videodec2ComputeQueue* compute_queue) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (compute_config_info == nullptr || compute_memory_info == nullptr ||
|
||||
compute_queue == nullptr) {
|
||||
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
|
||||
if (compute_config_info->this_size != sizeof(Videodec2ComputeConfigInfo) ||
|
||||
compute_memory_info->this_size != sizeof(Videodec2ComputeMemoryInfo)) {
|
||||
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
||||
if (compute_config_info->reserved0 != 0 || compute_config_info->reserved1 != 0) {
|
||||
return VIDEODEC2_ERROR_CONFIG_INFO;
|
||||
}
|
||||
|
||||
if (compute_config_info->compute_pipe_id > 4) {
|
||||
return VIDEODEC2_ERROR_COMPUTE_PIPE_ID;
|
||||
}
|
||||
|
||||
if (compute_config_info->compute_queue_id > 7) {
|
||||
return VIDEODEC2_ERROR_COMPUTE_QUEUE_ID;
|
||||
}
|
||||
|
||||
if (compute_memory_info->cpu_gpu_memory_size < VIDEODEC2_MIN_MEMORY_SIZE) {
|
||||
return VIDEODEC2_ERROR_MEMORY_SIZE;
|
||||
}
|
||||
|
||||
if (compute_memory_info->cpu_gpu_memory == nullptr) {
|
||||
return VIDEODEC2_ERROR_MEMORY_POINTER;
|
||||
}
|
||||
|
||||
*compute_queue = compute_memory_info->cpu_gpu_memory;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI ReleaseComputeQueue(Videodec2ComputeQueue compute_queue) {
|
||||
PRINT_NAME();
|
||||
|
||||
return compute_queue != nullptr ? OK : VIDEODEC2_ERROR_COMPUTE_QUEUE_ID;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI QueryDecoderMemoryInfo(const Videodec2DecoderConfigInfo* config,
|
||||
Videodec2DecoderMemoryInfo* memory_info) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (config == nullptr || memory_info == nullptr) {
|
||||
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
|
||||
if (config->this_size != sizeof(Videodec2DecoderConfigInfo) ||
|
||||
memory_info->this_size != sizeof(Videodec2DecoderMemoryInfo)) {
|
||||
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
||||
const auto validation_result = ValidateDecoderConfig(config);
|
||||
if (validation_result != OK) {
|
||||
return validation_result;
|
||||
}
|
||||
|
||||
memory_info->cpu_memory_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
||||
memory_info->cpu_memory = nullptr;
|
||||
memory_info->gpu_memory_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
||||
memory_info->gpu_memory = nullptr;
|
||||
memory_info->cpu_gpu_memory_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
||||
memory_info->cpu_gpu_memory = nullptr;
|
||||
memory_info->max_frame_buffer_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
||||
memory_info->frame_buffer_alignment = 0x100;
|
||||
memory_info->reserved0 = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI CreateDecoder(const Videodec2DecoderConfigInfo* config,
|
||||
const Videodec2DecoderMemoryInfo* memory_info,
|
||||
Videodec2Decoder* decoder) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (config == nullptr || memory_info == nullptr || decoder == nullptr) {
|
||||
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
|
||||
if (config->this_size != sizeof(Videodec2DecoderConfigInfo) ||
|
||||
memory_info->this_size != sizeof(Videodec2DecoderMemoryInfo)) {
|
||||
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
||||
const auto validation_result = ValidateDecoderConfig(config);
|
||||
if (validation_result != OK) {
|
||||
return validation_result;
|
||||
}
|
||||
|
||||
if (memory_info->cpu_memory_size < VIDEODEC2_MIN_MEMORY_SIZE ||
|
||||
memory_info->gpu_memory_size < VIDEODEC2_MIN_MEMORY_SIZE ||
|
||||
memory_info->cpu_gpu_memory_size < VIDEODEC2_MIN_MEMORY_SIZE ||
|
||||
memory_info->max_frame_buffer_size < VIDEODEC2_MIN_MEMORY_SIZE) {
|
||||
return VIDEODEC2_ERROR_MEMORY_SIZE;
|
||||
}
|
||||
|
||||
if (memory_info->cpu_memory == nullptr || memory_info->gpu_memory == nullptr ||
|
||||
memory_info->cpu_gpu_memory == nullptr) {
|
||||
return VIDEODEC2_ERROR_MEMORY_POINTER;
|
||||
}
|
||||
|
||||
auto* state = new DecoderState {};
|
||||
state->magic = DECODER_MAGIC;
|
||||
state->codec_type = config->codec_type;
|
||||
|
||||
{
|
||||
std::scoped_lock lock(g_decoder_mutex);
|
||||
g_decoders.insert(state);
|
||||
}
|
||||
|
||||
*decoder = state;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI DeleteDecoder(Videodec2Decoder decoder) {
|
||||
PRINT_NAME();
|
||||
|
||||
DecoderState* state = nullptr;
|
||||
{
|
||||
std::scoped_lock lock(g_decoder_mutex);
|
||||
auto it = g_decoders.find(decoder);
|
||||
if (it == g_decoders.end()) {
|
||||
return VIDEODEC2_ERROR_DECODER_INSTANCE;
|
||||
}
|
||||
state = static_cast<DecoderState*>(*it);
|
||||
g_decoders.erase(it);
|
||||
}
|
||||
|
||||
delete state;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI Decode(Videodec2Decoder decoder, const Videodec2InputData* input_data,
|
||||
Videodec2FrameBuffer* frame_buffer,
|
||||
Videodec2OutputInfo* output_info) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto* state = GetDecoder(decoder);
|
||||
if (state == nullptr || state->magic != DECODER_MAGIC) {
|
||||
return VIDEODEC2_ERROR_DECODER_INSTANCE;
|
||||
}
|
||||
|
||||
if (input_data == nullptr || frame_buffer == nullptr || output_info == nullptr) {
|
||||
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
|
||||
if (input_data->this_size != sizeof(Videodec2InputData) ||
|
||||
frame_buffer->this_size != sizeof(Videodec2FrameBuffer) ||
|
||||
!IsOutputInfoSizeValid(output_info->this_size)) {
|
||||
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
||||
if (input_data->au_size != 0 && input_data->au_data == nullptr) {
|
||||
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
|
||||
if (frame_buffer->frame_buffer_size == 0) {
|
||||
return VIDEODEC2_ERROR_FRAME_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (frame_buffer->frame_buffer == nullptr) {
|
||||
return VIDEODEC2_ERROR_FRAME_BUFFER_POINTER;
|
||||
}
|
||||
|
||||
frame_buffer->is_accepted = false;
|
||||
FillNoPictureOutput(frame_buffer, output_info, state->codec_type);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI Flush(Videodec2Decoder decoder, Videodec2FrameBuffer* frame_buffer,
|
||||
Videodec2OutputInfo* output_info) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto* state = GetDecoder(decoder);
|
||||
if (state == nullptr || state->magic != DECODER_MAGIC) {
|
||||
return VIDEODEC2_ERROR_DECODER_INSTANCE;
|
||||
}
|
||||
|
||||
if (frame_buffer == nullptr || output_info == nullptr) {
|
||||
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
|
||||
if (frame_buffer->this_size != sizeof(Videodec2FrameBuffer) ||
|
||||
!IsOutputInfoSizeValid(output_info->this_size)) {
|
||||
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
||||
frame_buffer->is_accepted = false;
|
||||
FillNoPictureOutput(frame_buffer, output_info, state->codec_type);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI Reset(Videodec2Decoder decoder) {
|
||||
PRINT_NAME();
|
||||
|
||||
const auto* state = GetDecoder(decoder);
|
||||
return state != nullptr && state->magic == DECODER_MAGIC ? OK
|
||||
: VIDEODEC2_ERROR_DECODER_INSTANCE;
|
||||
}
|
||||
|
||||
static int32_t KYTY_SYSV_ABI GetPictureInfo(const Videodec2OutputInfo* output_info,
|
||||
void* /*first_picture_info*/,
|
||||
void* /*second_picture_info*/) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (output_info == nullptr) {
|
||||
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
|
||||
if (!IsOutputInfoSizeValid(output_info->this_size)) {
|
||||
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitVideoDec2_1) {
|
||||
PRINT_NAME_ENABLE(true);
|
||||
|
||||
LIB_FUNC("RnDibcGCPKw", QueryComputeMemoryInfo);
|
||||
LIB_FUNC("eD+X2SmxUt4", AllocateComputeQueue);
|
||||
LIB_FUNC("UvtA3FAiF4Y", ReleaseComputeQueue);
|
||||
LIB_FUNC("qqMCwlULR+E", QueryDecoderMemoryInfo);
|
||||
LIB_FUNC("CNNRoRYd8XI", CreateDecoder);
|
||||
LIB_FUNC("jwImxXRGSKA", DeleteDecoder);
|
||||
LIB_FUNC("852F5+q6+iM", Decode);
|
||||
LIB_FUNC("l1hXwscLuCY", Flush);
|
||||
LIB_FUNC("wJXikG6QFN8", Reset);
|
||||
LIB_FUNC("NtXRa3dRzU0", GetPictureInfo);
|
||||
LIB_FUNC("kjrLbcyhEiw", GetPictureInfo);
|
||||
}
|
||||
|
||||
} // namespace VideoDec2
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "common/abi.h"
|
||||
#include "graphics/presentation/videoOut.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibGen5 {
|
||||
|
||||
LIB_VERSION("VideoOut", 1, "VideoOut", 1, 1);
|
||||
|
||||
LIB_DEFINE(InitVideoOut_1) {
|
||||
PRINT_NAME_ENABLE(true);
|
||||
|
||||
LIB_FUNC("Up36PTk687E", VideoOut::VideoOutOpen);
|
||||
LIB_FUNC("uquVH4-Du78", VideoOut::VideoOutClose);
|
||||
LIB_FUNC("PjS5uASwcV8", VideoOut::VideoOutSetBufferAttribute2);
|
||||
LIB_FUNC("rKBUtgRrtbk", VideoOut::VideoOutRegisterBuffers2);
|
||||
LIB_FUNC("HuViW4HnrOw", VideoOut::VideoOutSubmitChangeBufferAttribute2);
|
||||
LIB_FUNC("N5KDtkIjjJ4", VideoOut::VideoOutUnregisterBuffers);
|
||||
LIB_FUNC("CBiu4mCE1DA", VideoOut::VideoOutSetFlipRate);
|
||||
LIB_FUNC("HXzjK9yI30k", VideoOut::VideoOutAddFlipEvent);
|
||||
LIB_FUNC("Xru92wHJRmg", VideoOut::VideoOutAddVblankEvent);
|
||||
LIB_FUNC("keipklF0pMY", VideoOut::VideoOutAddPreVblankStartEvent);
|
||||
LIB_FUNC("-Ozn0F1AFRg", VideoOut::VideoOutDeleteFlipEvent);
|
||||
LIB_FUNC("oNOQn3knW6s", VideoOut::VideoOutDeleteVblankEvent);
|
||||
LIB_FUNC("elWQ9vERF-Q", VideoOut::VideoOutDeletePreVblankStartEvent);
|
||||
LIB_FUNC("U46NwOiJpys", VideoOut::VideoOutSubmitFlip);
|
||||
LIB_FUNC("SbU3dwp80lQ", VideoOut::VideoOutGetFlipStatus);
|
||||
LIB_FUNC("zgXifHT9ErY", VideoOut::VideoOutIsFlipPending);
|
||||
LIB_FUNC("1FZBKy8HeNU", VideoOut::VideoOutGetVblankStatus);
|
||||
LIB_FUNC("MTxxrOCeSig", VideoOut::VideoOutSetWindowModeMargins);
|
||||
LIB_FUNC("kmSe30JTs+E", VideoOut::VideoOutAddOutputModeEvent);
|
||||
LIB_FUNC("U2JJtSqNKZI", VideoOut::VideoOutGetEventId);
|
||||
LIB_FUNC("rWUTcKdkUzQ", VideoOut::VideoOutGetEventData);
|
||||
LIB_FUNC("Mt4QHHkxkOc", VideoOut::VideoOutGetEventCount);
|
||||
LIB_FUNC("j6RaAUlaLv0", VideoOut::VideoOutWaitVblank);
|
||||
LIB_FUNC("utPrVdxio-8", VideoOut::VideoOutGetOutputStatus);
|
||||
LIB_FUNC("+I4K03i3EL0", VideoOut::VideoOutInitializeOutputOptions);
|
||||
LIB_FUNC("Nv8c-Kb+DUM", VideoOut::VideoOutIsOutputSupported);
|
||||
LIB_FUNC("w0hLuNarQxY", VideoOut::VideoOutConfigureOutput);
|
||||
LIB_FUNC("eb-gvTYQcoY", VideoOut::VideoOutLatencyControlWaitBeforeInput);
|
||||
LIB_FUNC("MCJ8SkzsQxY", VideoOut::VideoOutLatencyMeasureSetStartPoint);
|
||||
LIB_FUNC("DYhhWbJSeRg", VideoOut::VideoOutColorSettingsSetGamma);
|
||||
LIB_FUNC("pv9CI5VC+R0", VideoOut::VideoOutAdjustColor);
|
||||
}
|
||||
|
||||
} // namespace LibGen5
|
||||
|
||||
LIB_DEFINE(InitVideoOut_1) {
|
||||
LibGen5::InitVideoOut_1(s);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,237 @@
|
||||
#include "libs/libs.h"
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/errno.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
namespace Libs {
|
||||
|
||||
namespace LibcInternal {
|
||||
LIB_DEFINE(InitLibcInternal_1);
|
||||
} // namespace LibcInternal
|
||||
|
||||
namespace LibContentDelete {
|
||||
LIB_DEFINE(InitContentDelete_1);
|
||||
} // namespace LibContentDelete
|
||||
|
||||
namespace LibContentExport {
|
||||
LIB_DEFINE(InitContentExport_1);
|
||||
} // namespace LibContentExport
|
||||
|
||||
namespace LibContentSearch {
|
||||
LIB_DEFINE(InitContentSearch_1);
|
||||
} // namespace LibContentSearch
|
||||
|
||||
namespace VideoDec2 {
|
||||
LIB_DEFINE(InitVideoDec2_1);
|
||||
} // namespace VideoDec2
|
||||
|
||||
namespace LibMouse {
|
||||
LIB_DEFINE(InitMouse_1);
|
||||
} // namespace LibMouse
|
||||
|
||||
namespace LibKeyboard {
|
||||
LIB_DEFINE(InitKeyboard_1);
|
||||
} // namespace LibKeyboard
|
||||
|
||||
namespace LibUlt {
|
||||
LIB_DEFINE(InitUlt_1);
|
||||
} // namespace LibUlt
|
||||
|
||||
namespace LibPsml {
|
||||
LIB_DEFINE(InitPsml_1);
|
||||
} // namespace LibPsml
|
||||
|
||||
LIB_DEFINE(InitLibC_1);
|
||||
LIB_DEFINE(InitAppContent_1);
|
||||
LIB_DEFINE(InitAmpr_1);
|
||||
LIB_DEFINE(InitAudio_1);
|
||||
LIB_DEFINE(InitCoredump_1);
|
||||
LIB_DEFINE(InitDbgAddressSanitizer_1);
|
||||
LIB_DEFINE(InitDebug_1);
|
||||
LIB_DEFINE(InitDialog_1);
|
||||
LIB_DEFINE(InitFiber_1);
|
||||
LIB_DEFINE(InitFont_1);
|
||||
LIB_DEFINE(InitFontFt_1);
|
||||
LIB_DEFINE(InitGraphicsDriver_1);
|
||||
LIB_DEFINE(InitLibKernel_1);
|
||||
LIB_DEFINE(InitNet_1);
|
||||
LIB_DEFINE(InitPad_1);
|
||||
LIB_DEFINE(InitPlayGo_1);
|
||||
LIB_DEFINE(InitPngDec_1);
|
||||
LIB_DEFINE(InitPlatform_1);
|
||||
LIB_DEFINE(InitRudp_1);
|
||||
LIB_DEFINE(InitRtc_1);
|
||||
LIB_DEFINE(InitSaveData_1);
|
||||
LIB_DEFINE(InitShare_1);
|
||||
LIB_DEFINE(InitSysmodule_1);
|
||||
LIB_DEFINE(InitSystemService_1);
|
||||
LIB_DEFINE(InitUserService_1);
|
||||
LIB_DEFINE(InitVideoOut_1);
|
||||
|
||||
void InitAll(Loader::SymbolDatabase* s) {
|
||||
LIB_LOAD(InitAudio_1);
|
||||
LIB_LOAD(InitAmpr_1);
|
||||
LIB_LOAD(InitAppContent_1);
|
||||
LIB_LOAD(InitCoredump_1);
|
||||
LIB_LOAD(LibContentDelete::InitContentDelete_1);
|
||||
LIB_LOAD(LibContentExport::InitContentExport_1);
|
||||
LIB_LOAD(LibContentSearch::InitContentSearch_1);
|
||||
LIB_LOAD(InitLibC_1);
|
||||
LIB_LOAD(InitDbgAddressSanitizer_1);
|
||||
LIB_LOAD(InitDebug_1);
|
||||
LIB_LOAD(InitDialog_1);
|
||||
LIB_LOAD(InitFiber_1);
|
||||
LIB_LOAD(InitFont_1);
|
||||
LIB_LOAD(InitFontFt_1);
|
||||
LIB_LOAD(InitGraphicsDriver_1);
|
||||
LIB_LOAD(InitLibKernel_1);
|
||||
LIB_LOAD(LibMouse::InitMouse_1);
|
||||
LIB_LOAD(LibKeyboard::InitKeyboard_1);
|
||||
LIB_LOAD(InitNet_1);
|
||||
LIB_LOAD(InitPad_1);
|
||||
LIB_LOAD(InitPlayGo_1);
|
||||
LIB_LOAD(LibPsml::InitPsml_1);
|
||||
LIB_LOAD(InitPngDec_1);
|
||||
LIB_LOAD(InitPlatform_1);
|
||||
LIB_LOAD(InitRudp_1);
|
||||
LIB_LOAD(InitRtc_1);
|
||||
LIB_LOAD(InitSaveData_1);
|
||||
LIB_LOAD(InitShare_1);
|
||||
LIB_LOAD(InitSysmodule_1);
|
||||
LIB_LOAD(InitSystemService_1);
|
||||
LIB_LOAD(LibUlt::InitUlt_1);
|
||||
LIB_LOAD(InitUserService_1);
|
||||
LIB_LOAD(VideoDec2::InitVideoDec2_1);
|
||||
LIB_LOAD(InitVideoOut_1);
|
||||
}
|
||||
|
||||
namespace LibContentExport {
|
||||
|
||||
LIB_VERSION("ContentExport", 1, "ContentExport", 1, 1);
|
||||
|
||||
namespace ContentExport {
|
||||
|
||||
constexpr int CONTENT_EXPORT_ERROR_INVALID_PARAM = -2137182186; /* 0x809D3016 */
|
||||
|
||||
struct ContentExportInitParam2 {
|
||||
void* malloc_func;
|
||||
void* free_func;
|
||||
void* user_data;
|
||||
size_t buffer_size;
|
||||
int64_t reserved0;
|
||||
int64_t reserved1;
|
||||
};
|
||||
|
||||
static bool g_initialized = false;
|
||||
|
||||
static int KYTY_SYSV_ABI ContentExportInit2(const ContentExportInitParam2* init_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t init_param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(init_param));
|
||||
|
||||
if (init_param == nullptr) {
|
||||
return CONTENT_EXPORT_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
LOGF("\t malloc_func = 0x%016" PRIx64 "\n"
|
||||
"\t free_func = 0x%016" PRIx64 "\n"
|
||||
"\t user_data = 0x%016" PRIx64 "\n"
|
||||
"\t buffer_size = %" PRIu64 "\n",
|
||||
reinterpret_cast<uint64_t>(init_param->malloc_func),
|
||||
reinterpret_cast<uint64_t>(init_param->free_func),
|
||||
reinterpret_cast<uint64_t>(init_param->user_data),
|
||||
static_cast<uint64_t>(init_param->buffer_size));
|
||||
|
||||
g_initialized = true;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace ContentExport
|
||||
|
||||
LIB_DEFINE(InitContentExport_1) {
|
||||
LIB_FUNC("0GnN4QCgIfs", ContentExport::ContentExportInit2);
|
||||
}
|
||||
|
||||
} // namespace LibContentExport
|
||||
|
||||
namespace LibContentSearch {
|
||||
|
||||
LIB_VERSION("ContentSearch", 1, "ContentSearch", 1, 0);
|
||||
|
||||
namespace ContentSearch {
|
||||
|
||||
constexpr int CONTENT_SEARCH_ERROR_INVALID_PARAM = -2137190397; /* 0x809D1003 */
|
||||
|
||||
struct ContentSearchInitParam {
|
||||
size_t memory_size;
|
||||
};
|
||||
|
||||
static bool g_initialized = false;
|
||||
|
||||
static int KYTY_SYSV_ABI ContentSearchInit(const ContentSearchInitParam* init_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t init_param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(init_param));
|
||||
|
||||
if (init_param == nullptr) {
|
||||
return CONTENT_SEARCH_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
LOGF("\t memory_size = %" PRIu64 "\n", static_cast<uint64_t>(init_param->memory_size));
|
||||
|
||||
g_initialized = true;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace ContentSearch
|
||||
|
||||
LIB_DEFINE(InitContentSearch_1) {
|
||||
LIB_FUNC("dPj4ZtRcIWk", ContentSearch::ContentSearchInit);
|
||||
}
|
||||
|
||||
} // namespace LibContentSearch
|
||||
|
||||
namespace LibContentDelete {
|
||||
|
||||
LIB_VERSION("ContentDelete", 1, "ContentDelete", 1, 1);
|
||||
|
||||
namespace ContentDelete {
|
||||
|
||||
constexpr int CONTENT_DELETE_ERROR_INVALID_PARAM = -2137174015; /* 0x809D5001 */
|
||||
|
||||
struct ContentDeleteInitParam {
|
||||
char reserved1[4];
|
||||
size_t heap_size;
|
||||
char reserved2[32];
|
||||
};
|
||||
|
||||
static bool g_initialized = false;
|
||||
|
||||
static int KYTY_SYSV_ABI ContentDeleteInitialize(const ContentDeleteInitParam* init_param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t init_param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(init_param));
|
||||
|
||||
if (init_param == nullptr) {
|
||||
return CONTENT_DELETE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
LOGF("\t heap_size = %" PRIu64 "\n", static_cast<uint64_t>(init_param->heap_size));
|
||||
|
||||
g_initialized = true;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace ContentDelete
|
||||
|
||||
LIB_DEFINE(InitContentDelete_1) {
|
||||
LIB_FUNC("zoxb0wEChEM", ContentDelete::ContentDeleteInitialize);
|
||||
}
|
||||
|
||||
} // namespace LibContentDelete
|
||||
|
||||
} // namespace Libs
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_LIBS_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_LIBS_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/threads.h"
|
||||
#include "loader/timer.h" // IWYU pragma: keep
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define PRINT_NAME_ENABLED g_print_name
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define PRINT_NAME_ENABLE(flag) PRINT_NAME_ENABLED = flag;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_DEFINE(name) void name(Loader::SymbolDatabase* s)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_NAME(l, m) \
|
||||
[[maybe_unused]] static thread_local bool PRINT_NAME_ENABLED = false; \
|
||||
static constexpr char g_library[] = l; \
|
||||
static constexpr char g_module[] = m;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_VERSION(l, lv, m, mv1, mv2) \
|
||||
LIB_NAME(l, m); \
|
||||
static constexpr int g_library_version = lv; \
|
||||
static constexpr int g_module_version_major = mv1; \
|
||||
static constexpr int g_module_version_minor = mv2;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_USING(n) \
|
||||
using n::g_library; \
|
||||
using n::g_library_version; \
|
||||
using n::g_module; \
|
||||
using n::g_module_version_major; \
|
||||
using n::g_module_version_minor;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_LOAD(name) name(s)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_ADD(n, f, t) \
|
||||
{ \
|
||||
Loader::SymbolResolve sr {}; \
|
||||
sr.name = n; \
|
||||
sr.library = g_library; \
|
||||
sr.library_version = g_library_version; \
|
||||
sr.module = g_module; \
|
||||
sr.module_version_major = g_module_version_major; \
|
||||
sr.module_version_minor = g_module_version_minor; \
|
||||
sr.type = t; \
|
||||
auto func = reinterpret_cast<uint64_t>(f); \
|
||||
const char* dbg_name = "" #f; \
|
||||
s->Add(sr, func, dbg_name); \
|
||||
}
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_OBJECT(n, f) LIB_ADD(n, f, Loader::SymbolType::Object)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_FUNC(n, f) LIB_ADD(n, f, Loader::SymbolType::Func)
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define PRINT_NAME() \
|
||||
if (PRINT_NAME_ENABLED) { \
|
||||
if (Log::GetDirection() != Log::Direction::Silent) { \
|
||||
const auto print_name_time = Loader::Timer::GetTime().ToString("HH24:MI:SS.FFF"); \
|
||||
LOGF_COLOR(Log::Color::Cyan, "[%d][%s] %s::%s::%s()\n", \
|
||||
Common::Thread::GetThreadIdUnique(), print_name_time.c_str(), g_library, \
|
||||
g_module, __func__); \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace Loader {
|
||||
class SymbolDatabase;
|
||||
} // namespace Loader
|
||||
|
||||
namespace Libs {
|
||||
|
||||
void InitAll(Loader::SymbolDatabase* s);
|
||||
|
||||
} // namespace Libs
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_LIBS_H_ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,188 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_NETWORK_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_NETWORK_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
#include "common/subsystems.h"
|
||||
|
||||
namespace Libs::Network {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Network);
|
||||
|
||||
namespace Net {
|
||||
|
||||
struct NetEtherAddr;
|
||||
|
||||
union NetEpollData {
|
||||
void* ptr;
|
||||
uint32_t u32;
|
||||
int fd;
|
||||
uint64_t u64;
|
||||
};
|
||||
|
||||
struct NetEpollEvent {
|
||||
uint32_t events;
|
||||
uint32_t reserved;
|
||||
uint64_t ident;
|
||||
NetEpollData data;
|
||||
};
|
||||
|
||||
static_assert(sizeof(NetEpollData) == 8);
|
||||
static_assert(sizeof(NetEpollEvent) == 24);
|
||||
|
||||
int KYTY_SYSV_ABI NetInit();
|
||||
int KYTY_SYSV_ABI NetTerm();
|
||||
int KYTY_SYSV_ABI NetPoolCreate(const char* name, int size, int flags);
|
||||
int KYTY_SYSV_ABI NetPoolDestroy(int memid);
|
||||
int KYTY_SYSV_ABI NetResolverCreate(const char* name, int memid, int flags);
|
||||
int KYTY_SYSV_ABI NetResolverStartNtoa(int rid, const char* hostname, void* addr, int timeout,
|
||||
int retry, int flags);
|
||||
int KYTY_SYSV_ABI NetInetPton(int af, const char* src, void* dst);
|
||||
const char* KYTY_SYSV_ABI NetInetNtop(int af, const void* src, char* dst, uint32_t size);
|
||||
int KYTY_SYSV_ABI NetEtherNtostr(const NetEtherAddr* n, char* str, size_t len);
|
||||
int KYTY_SYSV_ABI NetGetMacAddress(NetEtherAddr* addr, int flags);
|
||||
int KYTY_SYSV_ABI NetGetSockInfo(int s, void* info, int n, int flags);
|
||||
int KYTY_SYSV_ABI EpollCreate(const char* name, int flags);
|
||||
int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* event);
|
||||
int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int timeout);
|
||||
int KYTY_SYSV_ABI EpollDestroy(int eid);
|
||||
bool KYTY_SYSV_ABI IsSocket(int s);
|
||||
int KYTY_SYSV_ABI SocketClose(int s);
|
||||
int KYTY_SYSV_ABI Socket(int family, int type, int protocol);
|
||||
int KYTY_SYSV_ABI Bind(int s, const void* addr, uint32_t addrlen);
|
||||
int KYTY_SYSV_ABI Connect(int s, const void* addr, uint32_t addrlen);
|
||||
int KYTY_SYSV_ABI Listen(int s, int backlog);
|
||||
int KYTY_SYSV_ABI Accept(int s, void* addr, uint32_t* addrlen);
|
||||
int KYTY_SYSV_ABI Shutdown(int s, int how);
|
||||
int KYTY_SYSV_ABI Getsockname(int s, void* addr, uint32_t* addrlen);
|
||||
int KYTY_SYSV_ABI Getsockopt(int s, int level, int optname, void* optval, uint32_t* optlen);
|
||||
int KYTY_SYSV_ABI Setsockopt(int s, int level, int optname, const void* optval, uint32_t optlen);
|
||||
int KYTY_SYSV_ABI Select(int nfds, void* readfds, void* writefds, void* exceptfds,
|
||||
const void* timeout);
|
||||
int64_t KYTY_SYSV_ABI Send(int s, const void* buf, uint64_t len, int flags);
|
||||
int64_t KYTY_SYSV_ABI Recv(int s, void* buf, uint64_t len, int flags);
|
||||
|
||||
} // namespace Net
|
||||
|
||||
namespace Ssl {
|
||||
|
||||
int KYTY_SYSV_ABI SslInit(uint64_t pool_size);
|
||||
int KYTY_SYSV_ABI SslTerm(int ssl_ctx_id);
|
||||
int KYTY_SYSV_ABI SslGetCaCerts(int ssl_ctx_id, void* ca_certs);
|
||||
int KYTY_SYSV_ABI SslFreeCaCerts(int ssl_ctx_id, void* ca_certs);
|
||||
|
||||
} // namespace Ssl
|
||||
|
||||
namespace Http {
|
||||
|
||||
struct HttpEpoll;
|
||||
struct HttpNBEvent;
|
||||
|
||||
using HttpEpollHandle = HttpEpoll*;
|
||||
|
||||
using HttpsCallback = KYTY_SYSV_ABI int (*)(int, unsigned int, void* const*, int, void*);
|
||||
|
||||
int KYTY_SYSV_ABI HttpInit(int memid, int ssl_ctx_id, uint64_t pool_size);
|
||||
int KYTY_SYSV_ABI HttpTerm(int http_ctx_id);
|
||||
int KYTY_SYSV_ABI HttpCreateTemplate(int http_ctx_id, const char* user_agent, int http_ver,
|
||||
int is_auto_proxy_conf);
|
||||
int KYTY_SYSV_ABI HttpDeleteTemplate(int tmpl_id);
|
||||
int KYTY_SYSV_ABI HttpSetNonblock(int id, int enable);
|
||||
int KYTY_SYSV_ABI HttpCreateEpoll(int http_ctx_id, HttpEpollHandle* eh);
|
||||
int KYTY_SYSV_ABI HttpDestroyEpoll(int http_ctx_id, HttpEpollHandle eh);
|
||||
int KYTY_SYSV_ABI HttpCreateConnection(int tmpl_id, const char* server_name, const char* scheme,
|
||||
uint16_t port, int enable_keep_alive);
|
||||
int KYTY_SYSV_ABI HttpCreateConnectionWithURL(int tmpl_id, const char* url, int enable_keep_alive);
|
||||
int KYTY_SYSV_ABI HttpDeleteConnection(int conn_id);
|
||||
int KYTY_SYSV_ABI HttpCreateRequest(int conn_id, int method, const char* path,
|
||||
uint64_t content_length);
|
||||
int KYTY_SYSV_ABI HttpCreateRequestWithURL2(int conn_id, const char* method, const char* url,
|
||||
uint64_t content_length);
|
||||
int KYTY_SYSV_ABI HttpSetRequestContentLength(int request_id, uint64_t content_length);
|
||||
int KYTY_SYSV_ABI HttpDeleteRequest(int req_id);
|
||||
int KYTY_SYSV_ABI HttpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode);
|
||||
int KYTY_SYSV_ABI HttpSetEpoll(int id, HttpEpollHandle eh, void* user_arg);
|
||||
int KYTY_SYSV_ABI HttpUnsetEpoll(int id);
|
||||
int KYTY_SYSV_ABI HttpSendRequest(int request_id, const void* post_data, size_t size);
|
||||
int KYTY_SYSV_ABI HttpAbortRequest(int request_id);
|
||||
int KYTY_SYSV_ABI HttpWaitRequest(HttpEpollHandle eh, HttpNBEvent* nbev, int maxevents,
|
||||
int timeout);
|
||||
int KYTY_SYSV_ABI HttpGetStatusCode(int request_id, int* status_code);
|
||||
int KYTY_SYSV_ABI HttpGetAllResponseHeaders(int request_id, char** header, size_t* header_size);
|
||||
int KYTY_SYSV_ABI HttpGetResponseContentLength(int request_id, int* result,
|
||||
uint64_t* content_length);
|
||||
int KYTY_SYSV_ABI HttpsSetSslCallback(int id, HttpsCallback cbfunc, void* user_arg);
|
||||
int KYTY_SYSV_ABI HttpsSetMinSslVersion(int id, uint32_t ssl_version);
|
||||
int KYTY_SYSV_ABI HttpsDisableOption(int id, uint32_t ssl_flags);
|
||||
int KYTY_SYSV_ABI HttpSetResolveTimeOut(int id, uint32_t usec);
|
||||
int KYTY_SYSV_ABI HttpSetResolveRetry(int id, int32_t retry);
|
||||
int KYTY_SYSV_ABI HttpSetConnectTimeOut(int id, uint32_t usec);
|
||||
int KYTY_SYSV_ABI HttpSetSendTimeOut(int id, uint32_t usec);
|
||||
int KYTY_SYSV_ABI HttpSetRecvTimeOut(int id, uint32_t usec);
|
||||
int KYTY_SYSV_ABI HttpSetAutoRedirect(int id, int enable);
|
||||
int KYTY_SYSV_ABI HttpSetAuthEnabled(int id, int enable);
|
||||
|
||||
} // namespace Http
|
||||
|
||||
namespace NetCtl {
|
||||
|
||||
struct NetCtlNatInfo;
|
||||
union NetCtlInfo;
|
||||
|
||||
using NetCtlCallback = KYTY_SYSV_ABI void (*)(int, void*);
|
||||
|
||||
int KYTY_SYSV_ABI NetCtlInit();
|
||||
void KYTY_SYSV_ABI NetCtlTerm();
|
||||
int KYTY_SYSV_ABI NetCtlGetNatInfo(NetCtlNatInfo* nat_info);
|
||||
int KYTY_SYSV_ABI NetCtlCheckCallback();
|
||||
int KYTY_SYSV_ABI NetCtlGetState(int* state);
|
||||
int KYTY_SYSV_ABI NetCtlGetStateV6(int* state);
|
||||
int KYTY_SYSV_ABI NetCtlRegisterCallback(NetCtlCallback func, void* arg, int* cid);
|
||||
int KYTY_SYSV_ABI NetCtlUnregisterCallback(int cid);
|
||||
int KYTY_SYSV_ABI NetCtlGetResult(int event_type, int* error_code);
|
||||
int KYTY_SYSV_ABI NetCtlGetInfo(int code, NetCtlInfo* info);
|
||||
|
||||
} // namespace NetCtl
|
||||
|
||||
namespace NpManager {
|
||||
|
||||
struct NpTitleId;
|
||||
struct NpTitleSecret;
|
||||
struct NpContentRestriction;
|
||||
struct NpId;
|
||||
struct NpOnlineId;
|
||||
struct NpCreateAsyncRequestParameter;
|
||||
struct NpCheckPremiumParameter;
|
||||
struct NpCheckPremiumResult;
|
||||
|
||||
int KYTY_SYSV_ABI NpCheckCallback();
|
||||
int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret);
|
||||
int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restriction);
|
||||
int KYTY_SYSV_ABI NpRegisterStateCallback(void* callback, void* userdata);
|
||||
int KYTY_SYSV_ABI NpUnregisterStateCallback();
|
||||
void KYTY_SYSV_ABI NpRegisterGamePresenceCallback(void* callback, void* userdata);
|
||||
int KYTY_SYSV_ABI NpRegisterPlusEventCallback(void* callback, void* userdata);
|
||||
int KYTY_SYSV_ABI NpRegisterPremiumEventCallback(void* callback, void* userdata);
|
||||
int KYTY_SYSV_ABI NpRegisterNpReachabilityStateCallback(void* callback, void* userdata);
|
||||
int KYTY_SYSV_ABI NpGetNpId(int user_id, NpId* np_id);
|
||||
int KYTY_SYSV_ABI NpGetOnlineId(int user_id, NpOnlineId* online_id);
|
||||
int KYTY_SYSV_ABI NpGetAccountIdA(int user_id, uint64_t* account_id);
|
||||
int KYTY_SYSV_ABI NpGetAccountCountryA(int user_id, void* country_code);
|
||||
int KYTY_SYSV_ABI NpGetAccountAge(int req_id, int user_id, uint8_t* age);
|
||||
int KYTY_SYSV_ABI NpCreateRequest();
|
||||
int KYTY_SYSV_ABI NpCreateAsyncRequest(const NpCreateAsyncRequestParameter* param);
|
||||
int KYTY_SYSV_ABI NpDeleteRequest(int req_id);
|
||||
int KYTY_SYSV_ABI NpAbortRequest(int req_id);
|
||||
int KYTY_SYSV_ABI NpCheckNpAvailability(int req_id, const char* user, void* result);
|
||||
int KYTY_SYSV_ABI NpCheckNpReachability(int req_id, int user_id);
|
||||
int KYTY_SYSV_ABI NpPollAsync(int req_id, int* result);
|
||||
int KYTY_SYSV_ABI NpCheckPremium(int req_id, const NpCheckPremiumParameter* param,
|
||||
NpCheckPremiumResult* result);
|
||||
int KYTY_SYSV_ABI NpGetState(int user_id, uint32_t* state);
|
||||
int KYTY_SYSV_ABI NpGetNpReachabilityState(int user_id, uint32_t* state);
|
||||
|
||||
} // namespace NpManager
|
||||
|
||||
} // namespace Libs::Network
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_NETWORK_H_ */
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_PADDATA_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_PADDATA_H_
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
namespace Libs::Controller {
|
||||
|
||||
struct PadData {
|
||||
uint32_t buttons;
|
||||
uint8_t left_stick_x;
|
||||
uint8_t left_stick_y;
|
||||
uint8_t right_stick_x;
|
||||
uint8_t right_stick_y;
|
||||
uint8_t analog_buttons_l2;
|
||||
uint8_t analog_buttons_r2;
|
||||
uint8_t padding[2];
|
||||
float orientation_x;
|
||||
float orientation_y;
|
||||
float orientation_z;
|
||||
float orientation_w;
|
||||
float acceleration_x;
|
||||
float acceleration_y;
|
||||
float acceleration_z;
|
||||
float angular_velocity_x;
|
||||
float angular_velocity_y;
|
||||
float angular_velocity_z;
|
||||
uint8_t touch_data_touch_num;
|
||||
uint8_t touch_data_reserve[3];
|
||||
uint32_t touch_data_reserve1;
|
||||
uint16_t touch_data_touch0_x;
|
||||
uint16_t touch_data_touch0_y;
|
||||
uint8_t touch_data_touch0_id;
|
||||
uint8_t touch_data_touch0_reserve[3];
|
||||
uint16_t touch_data_touch1_x;
|
||||
uint16_t touch_data_touch1_y;
|
||||
uint8_t touch_data_touch1_id;
|
||||
uint8_t touch_data_touch1_reserve[3];
|
||||
bool connected;
|
||||
uint64_t timestamp;
|
||||
uint32_t extension_unit_data_extension_unit_id;
|
||||
uint8_t extension_unit_data_reserve[1];
|
||||
uint8_t extension_unit_data_data_length;
|
||||
uint8_t extension_unit_data_data[10];
|
||||
uint8_t connected_count;
|
||||
uint8_t reserve[2];
|
||||
uint8_t device_unique_data_len;
|
||||
uint8_t device_unique_data[12];
|
||||
};
|
||||
|
||||
static_assert(sizeof(PadData) == 120);
|
||||
|
||||
} // namespace Libs::Controller
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_PADDATA_H_ */
|
||||
@@ -0,0 +1,209 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <xmmintrin.h>
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define VA_ARGS \
|
||||
uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \
|
||||
uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \
|
||||
__m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ...
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define VA_CONTEXT(ctx) \
|
||||
alignas(16) VaContext ctx; \
|
||||
(ctx).reg_save_area.gp[0] = rdi; \
|
||||
(ctx).reg_save_area.gp[1] = rsi; \
|
||||
(ctx).reg_save_area.gp[2] = rdx; \
|
||||
(ctx).reg_save_area.gp[3] = rcx; \
|
||||
(ctx).reg_save_area.gp[4] = r8; \
|
||||
(ctx).reg_save_area.gp[5] = r9; \
|
||||
(ctx).reg_save_area.fp[0] = xmm0; \
|
||||
(ctx).reg_save_area.fp[1] = xmm1; \
|
||||
(ctx).reg_save_area.fp[2] = xmm2; \
|
||||
(ctx).reg_save_area.fp[3] = xmm3; \
|
||||
(ctx).reg_save_area.fp[4] = xmm4; \
|
||||
(ctx).reg_save_area.fp[5] = xmm5; \
|
||||
(ctx).reg_save_area.fp[6] = xmm6; \
|
||||
(ctx).reg_save_area.fp[7] = xmm7; \
|
||||
(ctx).va_list.reg_save_area = &(ctx).reg_save_area; \
|
||||
(ctx).va_list.gp_offset = offsetof(VaRegSave, gp); \
|
||||
(ctx).va_list.fp_offset = offsetof(VaRegSave, fp); \
|
||||
(ctx).va_list.overflow_arg_area = &overflow_arg_area;
|
||||
|
||||
namespace Libs {
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct VaList {
|
||||
uint32_t gp_offset;
|
||||
uint32_t fp_offset;
|
||||
void* overflow_arg_area;
|
||||
void* reg_save_area;
|
||||
};
|
||||
|
||||
// typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
||||
struct VaRegSave {
|
||||
uint64_t gp[6];
|
||||
__m128 fp[8];
|
||||
};
|
||||
|
||||
struct VaContext {
|
||||
VaRegSave reg_save_area;
|
||||
VaList va_list;
|
||||
};
|
||||
|
||||
struct VaCharX16 {
|
||||
char x[16];
|
||||
};
|
||||
|
||||
struct VaShortX8 {
|
||||
short x[8]; // NOLINT(google-runtime-int)
|
||||
};
|
||||
|
||||
struct VaIntX4 {
|
||||
int x[4];
|
||||
};
|
||||
|
||||
struct VaFloatX4 {
|
||||
float x[4];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
template <class T, uint64_t Align, uint64_t Size>
|
||||
T VaArg_overflow_arg_area(VaList* l) {
|
||||
auto ptr = ((reinterpret_cast<uint64_t>(l->overflow_arg_area) + (Align - 1)) & ~(Align - 1));
|
||||
auto* addr = reinterpret_cast<T*>(ptr);
|
||||
l->overflow_arg_area = reinterpret_cast<void*>(ptr + Size);
|
||||
return *addr;
|
||||
}
|
||||
|
||||
template <class T, uint32_t Size>
|
||||
T VaArg_reg_save_area_gp(VaList* l) {
|
||||
auto* addr = reinterpret_cast<T*>(static_cast<uint8_t*>(l->reg_save_area) + l->gp_offset);
|
||||
l->gp_offset += Size;
|
||||
return *addr;
|
||||
}
|
||||
|
||||
template <class T, uint32_t Size>
|
||||
T VaArg_reg_save_area_fp(VaList* l) {
|
||||
auto* addr = reinterpret_cast<T*>(static_cast<uint8_t*>(l->reg_save_area) + l->fp_offset);
|
||||
l->fp_offset += Size;
|
||||
return *addr;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline VaFloatX4 VaArg_reg_save_area_fp<VaFloatX4, 32>(VaList* l) {
|
||||
auto* addr =
|
||||
reinterpret_cast<VaFloatX4*>(static_cast<uint8_t*>(l->reg_save_area) + l->fp_offset);
|
||||
l->fp_offset += 32;
|
||||
VaFloatX4 ret = {{addr[0].x[0], addr[0].x[1], addr[1].x[0], addr[1].x[1]}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int VaArg_int(VaList* l) {
|
||||
if (l->gp_offset <= 40) {
|
||||
return VaArg_reg_save_area_gp<int, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<int, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline double VaArg_double(VaList* l) {
|
||||
if (l->fp_offset <= 160) {
|
||||
return VaArg_reg_save_area_fp<double, 16>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<double, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline long double VaArg_long_double(VaList* l) {
|
||||
return VaArg_overflow_arg_area<long double, 16, 16>(l);
|
||||
}
|
||||
|
||||
/*inline wint_t VaArg_wint_t(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<wint_t, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<wint_t, 1, 8>(l);
|
||||
}*/
|
||||
|
||||
inline VaCharX16 VaArg_char_x16(VaList* l) {
|
||||
if (l->gp_offset <= 32) {
|
||||
return VaArg_reg_save_area_gp<VaCharX16, 16>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<VaCharX16, 1, 16>(l);
|
||||
}
|
||||
|
||||
inline long VaArg_long(VaList* l) // NOLINT(google-runtime-int)
|
||||
{
|
||||
if (l->gp_offset <= 40) {
|
||||
return VaArg_reg_save_area_gp<long, 8>(l); // NOLINT(google-runtime-int)
|
||||
}
|
||||
return VaArg_overflow_arg_area<long, 1, 8>(l); // NOLINT(google-runtime-int)
|
||||
}
|
||||
|
||||
inline intmax_t VaArg_intmax_t(VaList* l) {
|
||||
if (l->gp_offset <= 40) {
|
||||
return VaArg_reg_save_area_gp<intmax_t, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<intmax_t, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline long long VaArg_long_long(VaList* l) // NOLINT(google-runtime-int)
|
||||
{
|
||||
if (l->gp_offset <= 40) {
|
||||
return VaArg_reg_save_area_gp<long long, 8>(l); // NOLINT(google-runtime-int)
|
||||
}
|
||||
return VaArg_overflow_arg_area<long long, 1, 8>(l); // NOLINT(google-runtime-int)
|
||||
}
|
||||
|
||||
inline ptrdiff_t VaArg_ptrdiff_t(VaList* l) {
|
||||
if (l->gp_offset <= 40) {
|
||||
return VaArg_reg_save_area_gp<ptrdiff_t, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<ptrdiff_t, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline size_t VaArg_size_t(VaList* l) {
|
||||
if (l->gp_offset <= 40) {
|
||||
return VaArg_reg_save_area_gp<size_t, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<size_t, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline VaShortX8 VaArg_ShortX8(VaList* l) {
|
||||
if (l->gp_offset <= 32) {
|
||||
return VaArg_reg_save_area_gp<VaShortX8, 16>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<VaShortX8, 1, 16>(l);
|
||||
}
|
||||
|
||||
inline VaIntX4 VaArg_IntX4(VaList* l) {
|
||||
if (l->gp_offset <= 32) {
|
||||
return VaArg_reg_save_area_gp<VaIntX4, 16>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<VaIntX4, 1, 16>(l);
|
||||
}
|
||||
|
||||
inline VaFloatX4 VaArg_FloatX4(VaList* l) {
|
||||
if (l->fp_offset <= 144) {
|
||||
return VaArg_reg_save_area_fp<VaFloatX4, 32>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<VaFloatX4, 1, 16>(l);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* VaArg_ptr(VaList* l) {
|
||||
if (l->gp_offset <= 40) {
|
||||
return VaArg_reg_save_area_gp<T*, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<T*, 1, 8>(l);
|
||||
}
|
||||
|
||||
} // namespace Libs
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_ */
|
||||
Reference in new issue
Block a user