This commit is contained in:
Peter Tissen 2014-03-19 14:38:42 +01:00
commit 27bb41d652
79 changed files with 2416 additions and 1089 deletions

View file

@ -10,21 +10,29 @@ if (CMAKE_COMPILER_IS_GNUCXX)
endif() endif()
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules)
SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/../bin") set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/../bin")
add_definitions(-DGL_GLEXT_PROTOTYPES) add_definitions(-DGL_GLEXT_PROTOTYPES)
add_definitions(-DGLX_GLXEXT_PROTOTYPES) add_definitions(-DGLX_GLXEXT_PROTOTYPES)
find_package(wxWidgets COMPONENTS core base net aui gl REQUIRED) find_package(wxWidgets COMPONENTS core base net aui gl REQUIRED)
find_package(GLEW REQUIRED)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
find_package(FFMPEG REQUIRED)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
find_package(OpenAL REQUIRED)
include("${wxWidgets_USE_FILE}") include("${wxWidgets_USE_FILE}")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(PLATFORM_ARCH "linux/x86_64")
else()
set(PLATFORM_ARCH "linux/x86")
endif()
include_directories( include_directories(
${wxWidgets_INCLUDE_DIRS} ${wxWidgets_INCLUDE_DIRS}
${FFMPEG_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/../ffmpeg/${PLATFORM_ARCH}/include
${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/Emu ${CMAKE_SOURCE_DIR}/Emu
${CMAKE_SOURCE_DIR}/Gui ${CMAKE_SOURCE_DIR}/Gui
@ -33,6 +41,8 @@ ${CMAKE_SOURCE_DIR}/Crypto
${CMAKE_SOURCE_DIR}/.. ${CMAKE_SOURCE_DIR}/..
) )
link_directories(${CMAKE_SOURCE_DIR}/../ffmpeg/${PLATFORM_ARCH}/lib)
file( file(
GLOB_RECURSE GLOB_RECURSE
RPCS3_SRC RPCS3_SRC
@ -48,5 +58,5 @@ ${CMAKE_SOURCE_DIR}/../Utilities/*
add_executable(rpcs3 ${RPCS3_SRC}) add_executable(rpcs3 ${RPCS3_SRC})
target_link_libraries(rpcs3 ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${ZLIB_LIBRARIES} ${FFMPEG_LIBRARIES}) target_link_libraries(rpcs3 ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARIES} ${OPENGL_LIBRARIES} libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES})

View file

@ -4,8 +4,8 @@
ALenum g_last_al_error = AL_NO_ERROR; ALenum g_last_al_error = AL_NO_ERROR;
ALCenum g_last_alc_error = ALC_NO_ERROR; ALCenum g_last_alc_error = ALC_NO_ERROR;
ALCdevice* pDevice; #define checkForAlError(sit) if((g_last_al_error = alGetError()) != AL_NO_ERROR) printAlError(g_last_al_error, sit)
ALCcontext* pContext; #define checkForAlcError(sit) if((g_last_alc_error = alcGetError(m_device)) != ALC_NO_ERROR) printAlcError(g_last_alc_error, sit)
void printAlError(ALenum err, const char* situation) void printAlError(ALenum err, const char* situation)
{ {
@ -25,120 +25,126 @@ void printAlcError(ALCenum err, const char* situation)
} }
} }
OpenALThread::~OpenALThread()
{
Quit();
}
void OpenALThread::Init() void OpenALThread::Init()
{ {
pDevice = alcOpenDevice(NULL); m_device = alcOpenDevice(nullptr);
checkForAlcError("alcOpenDevice"); checkForAlcError("alcOpenDevice");
pContext = alcCreateContext(pDevice, NULL); m_context = alcCreateContext(m_device, nullptr);
checkForAlcError("alcCreateContext"); checkForAlcError("alcCreateContext");
alcMakeContextCurrent(pContext); alcMakeContextCurrent(m_context);
checkForAlcError("alcMakeContextCurrent"); checkForAlcError("alcMakeContextCurrent");
} }
void OpenALThread::Quit() void OpenALThread::Quit()
{ {
for (SampleBuffer::iterator i = mBuffers.begin(); i != mBuffers.end(); i++) m_context = alcGetCurrentContext();
alDeleteBuffers(1, &i->second.mBufferID); m_device = alcGetContextsDevice(m_context);
alcMakeContextCurrent(nullptr);
alcMakeContextCurrent(NULL); alcDestroyContext(m_context);
alcDestroyContext(pContext); alcCloseDevice(m_device);
alcCloseDevice(pDevice);
} }
void OpenALThread::Play() void OpenALThread::Play()
{ {
alSourcePlay(mSource); ALint state;
checkForAlError("alSourcePlay"); alGetSourcei(m_source, AL_SOURCE_STATE, &state);
checkForAlError("alGetSourcei");
if(state != AL_PLAYING)
{
alSourcePlay(m_source);
checkForAlError("alSourcePlay");
}
} }
void OpenALThread::Close() void OpenALThread::Close()
{ {
alSourceStop(mSource); alSourceStop(m_source);
checkForAlError("alSourceStop"); checkForAlError("alSourceStop");
if (alIsSource(mSource)) if (alIsSource(m_source))
alDeleteSources(1, &mSource); alDeleteSources(1, &m_source);
alDeleteBuffers(g_al_buffers_count, m_buffers);
checkForAlError("alDeleteBuffers");
} }
void OpenALThread::Stop() void OpenALThread::Stop()
{ {
alSourceStop(mSource); alSourceStop(m_source);
checkForAlError("alSourceStop"); checkForAlError("alSourceStop");
} }
void OpenALThread::Open(const void* src, ALsizei size) void OpenALThread::Open(const void* src, ALsizei size)
{ {
alGenSources(1, &mSource); // WARNING: Memory leaks! alGenSources(1, &m_source);
checkForAlError("alGenSources"); checkForAlError("alGenSources");
alSourcei(mSource, AL_LOOPING, AL_FALSE); alGenBuffers(g_al_buffers_count, m_buffers);
checkForAlError("alGenBuffers");
alSourcei(m_source, AL_LOOPING, AL_FALSE);
checkForAlError("alSourcei"); checkForAlError("alSourcei");
mProcessed = 0; m_buffer_size = size;
mBuffer.mFreq = 48000;
mBuffer.mFormat = AL_FORMAT_STEREO16;
for (int i = 0; i < NUM_OF_BUFFERS; i++) for(uint i=0; i<g_al_buffers_count; ++i)
{ {
AddData(src, size); AddBlock(m_buffers[i], m_buffer_size, src);
} }
alSourceQueueBuffers(m_source, g_al_buffers_count, m_buffers);
checkForAlError("alSourceQueueBuffers");
Play();
} }
void OpenALThread::AddData(const void* src, ALsizei size) void OpenALThread::AddData(const void* src, ALsizei size)
{ {
alGenBuffers(1, &mBuffer.mBufferID); const char* bsrc = (const char*)src;
checkForAlError("alGenBuffers"); ALuint buffer;
ALint buffers_count;
alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &buffers_count);
checkForAlError("alGetSourcei");
mBuffers[mBuffer.mBufferID] = mBuffer; while(size)
AddBlock(mBuffer.mBufferID, size, src);
alSourceQueueBuffers(mSource, 1, &mBuffer.mBufferID);
checkForAlError("alSourceQueueBuffers");
alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &mProcessed);
while (mProcessed--)
{ {
alSourceUnqueueBuffers(mSource, 1, &mBuffer.mBufferID); if(buffers_count-- <= 0)
{
Play();
alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &buffers_count);
checkForAlError("alGetSourcei");
continue;
}
alSourceUnqueueBuffers(m_source, 1, &buffer);
checkForAlError("alSourceUnqueueBuffers"); checkForAlError("alSourceUnqueueBuffers");
alDeleteBuffers(1, &mBuffer.mBufferID); int bsize = size < m_buffer_size ? size : m_buffer_size;
checkForAlError("alDeleteBuffers"); AddBlock(buffer, bsize, bsrc);
alSourceQueueBuffers(m_source, 1, &buffer);
checkForAlError("alSourceQueueBuffers");
size -= bsize;
bsrc += bsize;
} }
Play();
} }
bool OpenALThread::AddBlock(ALuint bufferID, ALsizei size, const void* src) bool OpenALThread::AddBlock(const ALuint buffer_id, ALsizei size, const void* src)
{ {
memset(&mTempBuffer, 0, sizeof(mTempBuffer));
memcpy(mTempBuffer, src, size);
long TotalRet = 0, ret;
if (size < 1) return false; if (size < 1) return false;
while (TotalRet < size) alBufferData(buffer_id, AL_FORMAT_STEREO16, src, size, 48000);
{
ret = size;
// if buffer is empty
if (ret == 0) break;
else if (ret < 0)
{
ConLog.Error("Error in bitstream!");
}
else
{
TotalRet += ret;
}
}
if (TotalRet > 0)
{
alBufferData(bufferID, mBuffers[bufferID].mFormat, mTempBuffer,
TotalRet, mBuffers[bufferID].mFreq);
checkForAlError("alBufferData"); checkForAlError("alBufferData");
}
return (ret > 0); return true;
} }

View file

@ -1,49 +1,29 @@
#pragma once #pragma once
#include "OpenAL\include\al.h" #include "OpenAL/include/al.h"
#include "OpenAL\include\alc.h" #include "OpenAL/include/alc.h"
#include <map>
extern ALenum g_last_al_error;
extern ALCenum g_last_alc_error;
void printAlError(ALenum err, const char* situation);
void printAlcError(ALCenum err, const char* situation);
#define checkForAlError(sit) if((g_last_al_error = alGetError()) != AL_NO_ERROR) printAlError(g_last_al_error, sit)
#define checkForAlcError(sit) if((g_last_alc_error = alcGetError(pDevice)) != ALC_NO_ERROR) printAlcError(g_last_alc_error, sit)
struct SampleInfo
{
uint mBufferID;
uint mFreq;
uint mFormat;
};
typedef std::map<ALuint, SampleInfo> SampleBuffer;
#define NUM_OF_BUFFERS 16
extern ALCdevice* pDevice;
extern ALCcontext* pContext;
class OpenALThread class OpenALThread
{ {
private: private:
ALuint mSource; static const uint g_al_buffers_count = 16;
SampleBuffer mBuffers;
SampleInfo mBuffer; ALuint m_source;
ALint mProcessed; ALuint m_buffers[g_al_buffers_count];
u16 mTempBuffer[512]; ALCdevice* m_device;
ALCcontext* m_context;
u32 m_buffer_size;
public: public:
~OpenALThread();
void Init(); void Init();
void Quit(); void Quit();
void Play(); void Play();
void Open(const void* src, ALsizei size); void Open(const void* src, ALsizei size);
void Close(); void Close();
void Stop(); void Stop();
bool AddBlock(ALuint bufferID, ALsizei size, const void* src); bool AddBlock(const ALuint buffer_id, ALsizei size, const void* src);
void AddData(const void* src, ALsizei size); void AddData(const void* src, ALsizei size);
}; };

View file

@ -24,8 +24,6 @@ void AudioDumper::WriteHeader()
size_t AudioDumper::WriteData(const void* buffer, size_t size) size_t AudioDumper::WriteData(const void* buffer, size_t size)
{ {
size_t ret = m_output.Write(buffer, size); size_t ret = m_output.Write(buffer, size);
return ret; return ret;
} }

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "sysutil_audio.h" #include "sysutil_audio.h"
#include "AL\OpenALThread.h" #include "AL/OpenALThread.h"
struct AudioInfo struct AudioInfo
{ {
@ -44,3 +44,4 @@ public:
}; };
extern OpenALThread* m_audio_out; extern OpenALThread* m_audio_out;

View file

@ -121,6 +121,7 @@ struct AudioPortConfig
struct AudioConfig //custom structure struct AudioConfig //custom structure
{ {
std::mutex m_mutex;
enum enum
{ {
AUDIO_PORT_COUNT = 8, AUDIO_PORT_COUNT = 8,
@ -131,15 +132,14 @@ struct AudioConfig //custom structure
bool m_is_audio_initialized; bool m_is_audio_initialized;
bool m_is_audio_finalized; bool m_is_audio_finalized;
u32 m_port_in_use; u32 m_port_in_use;
u64 event_key;
u64 counter; u64 counter;
u64 start_time; u64 start_time;
Array<u64> m_keys;
AudioConfig() AudioConfig()
: m_is_audio_initialized(false) : m_is_audio_initialized(false)
, m_is_audio_finalized(false) , m_is_audio_finalized(false)
, m_port_in_use(0) , m_port_in_use(0)
, event_key(0)
, counter(0) , counter(0)
{ {
memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT); memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT);

View file

@ -393,7 +393,7 @@ s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
ConLog.Warning("ExecAsCallback() aborted"); ConLog.Warning("ExecAsCallback(wait=%s) aborted", wxString(wait ? "true" : "false").wx_str());
return CELL_EABORT; // doesn't mean anything return CELL_EABORT; // doesn't mean anything
} }
Sleep(1); Sleep(1);

View file

@ -18,6 +18,7 @@ enum
MFC_BARRIER_MASK = 0x01, MFC_BARRIER_MASK = 0x01,
MFC_FENCE_MASK = 0x02, MFC_FENCE_MASK = 0x02,
MFC_LIST_MASK = 0x04,
MFC_MASK_CMD = 0xffff, MFC_MASK_CMD = 0xffff,
}; };
@ -165,7 +166,7 @@ struct DMAC
//returns true if the command should be deleted from the queue //returns true if the command should be deleted from the queue
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK))
{ {
case MFC_PUT_CMD: case MFC_PUT_CMD:
Memory.Copy(ea, ls_offset + lsa, size); Memory.Copy(ea, ls_offset + lsa, size);
@ -176,7 +177,7 @@ struct DMAC
return true; return true;
default: default:
ConLog.Error("Unknown DMA cmd."); ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd.");
return true; return true;
} }
} }

View file

@ -1206,6 +1206,13 @@ private:
{ {
DisAsm_R2_INT2_RC("rldimi", ra, rs, sh, mb, rc); DisAsm_R2_INT2_RC("rldimi", ra, rs, sh, mb, rc);
} }
void RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, bool is_r, bool rc)
{
if (is_r)
DisAsm_R3_INT2_RC("rldcr", ra, rs, rb, m_eb, 0, rc);
else
DisAsm_R3_INT2_RC("rldcl", ra, rs, rb, m_eb, 0, rc);
}
void CMP(u32 crfd, u32 l, u32 ra, u32 rb) void CMP(u32 crfd, u32 l, u32 ra, u32 rb)
{ {
DisAsm_CR1_R2(wxString::Format("cmp%s", wxString(l ? "d" : "w").wx_str()), crfd, ra, rb); DisAsm_CR1_R2(wxString::Format("cmp%s", wxString(l ? "d" : "w").wx_str()), crfd, ra, rb);
@ -1614,6 +1621,10 @@ private:
{ {
DisAsm_V1_R2("lvlx", vd, ra, rb); DisAsm_V1_R2("lvlx", vd, ra, rb);
} }
void LDBRX(u32 rd, u32 ra, u32 rb)
{
DisAsm_R3("ldbrx", rd, ra, rb);
}
void LWBRX(u32 rd, u32 ra, u32 rb) void LWBRX(u32 rd, u32 ra, u32 rb)
{ {
DisAsm_R3("lwbrx", rd, ra, rb); DisAsm_R3("lwbrx", rd, ra, rb);

View file

@ -193,7 +193,7 @@ namespace PPU_instr
static CodeField<26, 31> GD_04; //0x3f static CodeField<26, 31> GD_04; //0x3f
static CodeField<21, 31> GD_04_0;//0x7ff static CodeField<21, 31> GD_04_0;//0x7ff
static CodeField<21, 30> GD_13; //0x3ff static CodeField<21, 30> GD_13; //0x3ff
static CodeField<28, 29> GD_1e; //0x3 static CodeField<27, 29> GD_1e; //0x7
static CodeField<21, 30> GD_1f; //0x3ff static CodeField<21, 30> GD_1f; //0x3ff
static CodeField<30, 31> GD_3a; //0x3 static CodeField<30, 31> GD_3a; //0x3
static CodeField<26, 30> GD_3b; //0x1f static CodeField<26, 30> GD_3b; //0x1f
@ -441,6 +441,7 @@ namespace PPU_instr
bind_instr(g1e_list, RLDICR, RA, RS, sh, me, RC); bind_instr(g1e_list, RLDICR, RA, RS, sh, me, RC);
bind_instr(g1e_list, RLDIC, RA, RS, sh, mb, RC); bind_instr(g1e_list, RLDIC, RA, RS, sh, mb, RC);
bind_instr(g1e_list, RLDIMI, RA, RS, sh, mb, RC); bind_instr(g1e_list, RLDIMI, RA, RS, sh, mb, RC);
bind_instr(g1e_list, RLDC_LR, RA, RS, RB, mb, AA, RC);
/*0x000*/bind_instr(g1f_list, CMP, CRFD, L_10, RA, RB); /*0x000*/bind_instr(g1f_list, CMP, CRFD, L_10, RA, RB);
/*0x004*/bind_instr(g1f_list, TW, TO, RA, RB); /*0x004*/bind_instr(g1f_list, TW, TO, RA, RB);
@ -529,6 +530,7 @@ namespace PPU_instr
/*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC); /*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC);
/*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC); /*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC);
/*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB); /*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB);
/*0x214*/bind_instr(g1f_list, LDBRX, RD, RA, RB);
/*0x216*/bind_instr(g1f_list, LWBRX, RD, RA, RB); /*0x216*/bind_instr(g1f_list, LWBRX, RD, RA, RB);
/*0x217*/bind_instr(g1f_list, LFSX, FRD, RA, RB); /*0x217*/bind_instr(g1f_list, LFSX, FRD, RA, RB);
/*0x218*/bind_instr(g1f_list, SRW, RA, RS, RB, RC); /*0x218*/bind_instr(g1f_list, SRW, RA, RS, RB, RC);

View file

@ -2238,6 +2238,17 @@ private:
CPU.GPR[ra] = (CPU.GPR[ra] & ~mask) | (rotl64(CPU.GPR[rs], sh) & mask); CPU.GPR[ra] = (CPU.GPR[ra] & ~mask) | (rotl64(CPU.GPR[rs], sh) & mask);
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]); if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
} }
void RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, bool is_r, bool rc)
{
if (is_r) // rldcr
{
RLDICR(ra, rs, CPU.GPR[rb], m_eb, rc);
}
else // rldcl
{
RLDICL(ra, rs, CPU.GPR[rb], m_eb, rc);
}
}
void CMP(u32 crfd, u32 l, u32 ra, u32 rb) void CMP(u32 crfd, u32 l, u32 ra, u32 rb)
{ {
CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], CPU.GPR[rb]); CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], CPU.GPR[rb]);
@ -2313,8 +2324,7 @@ private:
#ifdef _M_X64 #ifdef _M_X64
CPU.GPR[rd] = __umulh(CPU.GPR[ra], CPU.GPR[rb]); CPU.GPR[rd] = __umulh(CPU.GPR[ra], CPU.GPR[rb]);
#else #else
ConLog.Warning("MULHDU"); //ConLog.Warning("MULHDU");
const u64 RA = CPU.GPR[ra]; const u64 RA = CPU.GPR[ra];
const u64 RB = CPU.GPR[rb]; const u64 RB = CPU.GPR[rb];
@ -2520,7 +2530,7 @@ private:
#ifdef _M_X64 #ifdef _M_X64
CPU.GPR[rd] = __mulh(CPU.GPR[ra], CPU.GPR[rb]); CPU.GPR[rd] = __mulh(CPU.GPR[ra], CPU.GPR[rb]);
#else #else
ConLog.Warning("MULHD"); //ConLog.Warning("MULHD");
const s64 RA = CPU.GPR[ra]; const s64 RA = CPU.GPR[ra];
const s64 RB = CPU.GPR[rb]; const s64 RB = CPU.GPR[rb];
@ -2782,7 +2792,7 @@ private:
} }
void MULLW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) void MULLW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
{ {
CPU.GPR[rd] = (s64)(s32)((s32)CPU.GPR[ra] * (s32)CPU.GPR[rb]); CPU.GPR[rd] = (s64)((s64)(s32)CPU.GPR[ra] * (s64)(s32)CPU.GPR[rb]);
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[rd]); if(rc) CPU.UpdateCR0<s32>(CPU.GPR[rd]);
if(oe) UNK("mullwo"); if(oe) UNK("mullwo");
} }
@ -2965,7 +2975,7 @@ private:
if (RB == 0 || ((u64)RA == (1ULL << 63) && RB == -1)) if (RB == 0 || ((u64)RA == (1ULL << 63) && RB == -1))
{ {
if(oe) UNK("divdo"); if(oe) UNK("divdo");
CPU.GPR[rd] = (((u64)RA & (1ULL << 63)) && RB == 0) ? -1 : 0; CPU.GPR[rd] = /*(((u64)RA & (1ULL << 63)) && RB == 0) ? -1 :*/ 0;
} }
else else
{ {
@ -2982,11 +2992,11 @@ private:
if (RB == 0 || ((u32)RA == (1 << 31) && RB == -1)) if (RB == 0 || ((u32)RA == (1 << 31) && RB == -1))
{ {
if(oe) UNK("divwo"); if(oe) UNK("divwo");
CPU.GPR[rd] = (((u32)RA & (1 << 31)) && RB == 0) ? -1 : 0; CPU.GPR[rd] = /*(((u32)RA & (1 << 31)) && RB == 0) ? -1 :*/ 0;
} }
else else
{ {
CPU.GPR[rd] = (s64)(RA / RB); CPU.GPR[rd] = (u32)(RA / RB);
} }
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[rd]); if(rc) CPU.UpdateCR0<s32>(CPU.GPR[rd]);
@ -2998,6 +3008,10 @@ private:
Memory.ReadLeft(CPU.VPR[vd]._u8 + eb, addr, 16 - eb); Memory.ReadLeft(CPU.VPR[vd]._u8 + eb, addr, 16 - eb);
} }
void LDBRX(u32 rd, u32 ra, u32 rb)
{
CPU.GPR[rd] = (u64&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]];
}
void LWBRX(u32 rd, u32 ra, u32 rb) void LWBRX(u32 rd, u32 ra, u32 rb)
{ {
CPU.GPR[rd] = (u32&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]]; CPU.GPR[rd] = (u32&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]];
@ -3093,18 +3107,34 @@ private:
void SRAW(u32 ra, u32 rs, u32 rb, bool rc) void SRAW(u32 ra, u32 rs, u32 rb, bool rc)
{ {
s32 RS = CPU.GPR[rs]; s32 RS = CPU.GPR[rs];
s32 RB = CPU.GPR[rb]; u8 shift = CPU.GPR[rb] & 63;
CPU.GPR[ra] = RS >> RB; if (shift > 31)
CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << RB) != RS); {
CPU.GPR[ra] = 0 - (RS < 0);
CPU.XER.CA = (RS < 0);
}
else
{
CPU.GPR[ra] = RS >> shift;
CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << shift) != RS);
}
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]); if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
} }
void SRAD(u32 ra, u32 rs, u32 rb, bool rc) void SRAD(u32 ra, u32 rs, u32 rb, bool rc)
{ {
s64 RS = CPU.GPR[rs]; s64 RS = CPU.GPR[rs];
s64 RB = CPU.GPR[rb]; u8 shift = CPU.GPR[rb] & 127;
CPU.GPR[ra] = RS >> RB; if (shift > 63)
CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << RB) != RS); {
CPU.GPR[ra] = 0 - (RS < 0);
CPU.XER.CA = (RS < 0);
}
else
{
CPU.GPR[ra] = RS >> shift;
CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << shift) != RS);
}
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]); if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
} }
@ -3178,6 +3208,7 @@ private:
void EXTSW(u32 ra, u32 rs, bool rc) void EXTSW(u32 ra, u32 rs, bool rc)
{ {
CPU.GPR[ra] = (s64)(s32)CPU.GPR[rs]; CPU.GPR[ra] = (s64)(s32)CPU.GPR[rs];
//CPU.XER.CA = ((s64)CPU.GPR[ra] < 0); // ???
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[ra]); if(rc) CPU.UpdateCR0<s32>(CPU.GPR[ra]);
} }
/*0x3d6*///ICBI /*0x3d6*///ICBI
@ -3389,62 +3420,11 @@ private:
} }
void FRES(u32 frd, u32 frb, bool rc) void FRES(u32 frd, u32 frb, bool rc)
{ {
double res;
#ifdef _MSC_VER
if(_fpclass(CPU.FPR[frb]) >= _FPCLASS_NZ)
#else
if(_fpclass(CPU.FPR[frb]) == FP_ZERO || std::signbit(CPU.FPR[frb]) == 0)
#endif
{
res = static_cast<float>(1.0 / CPU.FPR[frb]);
if(FPRdouble::IsINF(res) && CPU.FPR[frb] != 0.0)
{
if(res > 0.0)
{
(u64&)res = 0x47EFFFFFE0000000ULL;
}
else
{
(u64&)res = 0xC7EFFFFFE0000000ULL;
}
}
}
else
{
u64 v = CPU.FPR[frb];
if(v == 0ULL)
{
v = 0x7FF0000000000000ULL;
}
else if(v == 0x8000000000000000ULL)
{
v = 0xFFF0000000000000ULL;
}
else if(FPRdouble::IsNaN(CPU.FPR[frb]))
{
v = 0x7FF8000000000000ULL;
}
else if(CPU.FPR[frb] < 0.0)
{
v = 0x8000000000000000ULL;
}
else
{
v = 0ULL;
}
res = (double&)v;
}
if(CPU.FPR[frb] == 0.0) if(CPU.FPR[frb] == 0.0)
{ {
CPU.SetFPSCRException(FPSCR_ZX); CPU.SetFPSCRException(FPSCR_ZX);
} }
CPU.FPR[frd] = static_cast<float>(1.0 / CPU.FPR[frb]);
CPU.FPR[frd] = res;
if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]); if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]);
} }
void FMULS(u32 frd, u32 fra, u32 frc, bool rc) void FMULS(u32 frd, u32 fra, u32 frc, bool rc)
@ -3775,8 +3755,12 @@ private:
} }
void FRSQRTE(u32 frd, u32 frb, bool rc) void FRSQRTE(u32 frd, u32 frb, bool rc)
{ {
UNIMPLEMENTED(); if(CPU.FPR[frb] == 0.0)
//CPU.FPR[frd] = 1.0f / (float)sqrt(CPU.FPR[frb]); {
CPU.SetFPSCRException(FPSCR_ZX);
}
CPU.FPR[frd] = static_cast<float>(1.0 / sqrt(CPU.FPR[frb]));
if(rc) UNK("frsqrte.");//CPU.UpdateCR1(CPU.FPR[frd]);
} }
void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{ {

View file

@ -250,6 +250,7 @@ namespace PPU_opcodes
RLDICR = 0x1, RLDICR = 0x1,
RLDIC = 0x2, RLDIC = 0x2,
RLDIMI = 0x3, RLDIMI = 0x3,
RLDC_LR = 0x4,
}; };
enum G_1fOpcodes //Field 21 - 30 enum G_1fOpcodes //Field 21 - 30
@ -342,6 +343,7 @@ namespace PPU_opcodes
DIVD = 0x1e9, DIVD = 0x1e9,
DIVW = 0x1eb, DIVW = 0x1eb,
LVLX = 0x207, //Load Vector Left Indexed LVLX = 0x207, //Load Vector Left Indexed
LDBRX = 0x214,
LWBRX = 0x216, LWBRX = 0x216,
LFSX = 0x217, LFSX = 0x217,
SRW = 0x218, SRW = 0x218,
@ -646,6 +648,7 @@ public:
virtual void RLDICR(u32 ra, u32 rs, u32 sh, u32 me, bool rc) = 0; virtual void RLDICR(u32 ra, u32 rs, u32 sh, u32 me, bool rc) = 0;
virtual void RLDIC(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) = 0; virtual void RLDIC(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) = 0;
virtual void RLDIMI(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) = 0; virtual void RLDIMI(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) = 0;
virtual void RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, bool is_r, bool rc) = 0;
virtual void CMP(u32 crfd, u32 l, u32 ra, u32 rb) = 0; virtual void CMP(u32 crfd, u32 l, u32 ra, u32 rb) = 0;
virtual void TW(u32 to, u32 ra, u32 rb) = 0; virtual void TW(u32 to, u32 ra, u32 rb) = 0;
virtual void LVSL(u32 vd, u32 ra, u32 rb) = 0; virtual void LVSL(u32 vd, u32 ra, u32 rb) = 0;
@ -733,6 +736,7 @@ public:
virtual void DIVD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0; virtual void DIVD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
virtual void DIVW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0; virtual void DIVW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
virtual void LVLX(u32 vd, u32 ra, u32 rb) = 0; virtual void LVLX(u32 vd, u32 ra, u32 rb) = 0;
virtual void LDBRX(u32 rd, u32 ra, u32 rb) = 0;
virtual void LWBRX(u32 rd, u32 ra, u32 rb) = 0; virtual void LWBRX(u32 rd, u32 ra, u32 rb) = 0;
virtual void LFSX(u32 frd, u32 ra, u32 rb) = 0; virtual void LFSX(u32 frd, u32 ra, u32 rb) = 0;
virtual void SRW(u32 ra, u32 rs, u32 rb, bool rc) = 0; virtual void SRW(u32 ra, u32 rs, u32 rb, bool rc) = 0;

View file

@ -526,7 +526,7 @@ static const s32 MAX_INT_VALUE = 0x7fffffff;
class PPUThread : public PPCThread class PPUThread : public PPCThread
{ {
public: public:
std::atomic<u32> owned_mutexes; u32 owned_mutexes;
public: public:
PPCdouble FPR[32]; //Floating Point Register PPCdouble FPR[32]; //Floating Point Register

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "PPCThread.h" #include "PPCThread.h"
#include "Emu/event.h" #include "Emu/event.h"
#include "Emu/SysCalls/lv2/SC_SPU_Thread.h"
#include "MFC.h" #include "MFC.h"
#include <mutex> #include <mutex>
@ -484,6 +485,22 @@ public:
Channel<1> AtomicStat; Channel<1> AtomicStat;
} Prxy; } Prxy;
struct StalledList
{
u32 lsa;
u64 ea;
u16 tag;
u16 size;
u32 cmd;
MFCReg* MFCArgs;
StalledList()
: MFCArgs(nullptr)
{
}
} StallList[32];
Channel<1> StallStat;
struct struct
{ {
Channel<1> Out_MBox; Channel<1> Out_MBox;
@ -505,6 +522,66 @@ public:
DMAC dmac; DMAC dmac;
void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs)
{
u32 list_addr = ea & 0x3ffff;
u32 list_size = size / 8;
lsa &= 0x3fff0;
struct list_element
{
be_t<u16> s; // Stall-and-Notify bit (0x8000)
be_t<u16> ts; // List Transfer Size
be_t<u32> ea; // External Address Low
};
u32 result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
for (u32 i = 0; i < list_size; i++)
{
mem_ptr_t<list_element> rec(dmac.ls_offset + list_addr + i * 8);
u32 size = rec->ts;
if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
{
ConLog.Error("DMA List: invalid transfer size(%d)", size);
return;
}
u32 addr = rec->ea;
result = dmac.Cmd(cmd, tag, lsa | (addr & 0xf), addr, size);
if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR)
{
break;
}
if (Ini.HLELogging.GetValue() || rec->s)
ConLog.Write("*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)",
i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf));
lsa += max(size, (u32)16);
if (rec->s & se16(0x8000))
{
StallStat.PushUncond_OR(1 << tag);
if (StallList[tag].MFCArgs)
{
ConLog.Error("DMA List: existing stalled list found (tag=%d)", tag);
}
StallList[tag].MFCArgs = &MFCArgs;
StallList[tag].cmd = cmd;
StallList[tag].ea = (ea & ~0xffffffff) | (list_addr + (i + 1) * 8);
StallList[tag].lsa = lsa;
StallList[tag].size = (list_size - i - 1) * 8;
return;
}
}
MFCArgs.CMDStatus.SetValue(result);
}
void EnqMfcCmd(MFCReg& MFCArgs) void EnqMfcCmd(MFCReg& MFCArgs)
{ {
u32 cmd = MFCArgs.CMDStatus.GetValue(); u32 cmd = MFCArgs.CMDStatus.GetValue();
@ -528,7 +605,7 @@ public:
lsa, ea, tag, size, cmd); lsa, ea, tag, size, cmd);
if (op & MFC_PUT_CMD) if (op & MFC_PUT_CMD)
{ {
SMutexLocker lock(reservation.mutex); SMutexLocker lock(reservation.mutex); // should be removed
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) || if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) ||
(ea + size > reservation.addr && ea <= reservation.addr + reservation.size)) (ea + size > reservation.addr && ea <= reservation.addr + reservation.size))
@ -543,6 +620,19 @@ public:
} }
break; break;
case MFC_PUTL_CMD:
case MFC_GETL_CMD:
{
if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
wxString(op & MFC_PUT_CMD ? "PUTL" : "GETL").wx_str(),
wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(),
wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(),
lsa, ea, tag, size, cmd);
ListCmd(lsa, ea, tag, size, cmd, MFCArgs);
}
break;
case MFC_GETLLAR_CMD: case MFC_GETLLAR_CMD:
case MFC_PUTLLC_CMD: case MFC_PUTLLC_CMD:
case MFC_PUTLLUC_CMD: case MFC_PUTLLUC_CMD:
@ -628,6 +718,9 @@ public:
case MFC_RdTagStat: case MFC_RdTagStat:
return Prxy.TagStatus.GetCount(); return Prxy.TagStatus.GetCount();
case MFC_RdListStallStat:
return StallStat.GetCount();
case MFC_WrTagUpdate: case MFC_WrTagUpdate:
return Prxy.TagStatus.GetCount(); // hack return Prxy.TagStatus.GetCount(); // hack
@ -751,6 +844,24 @@ public:
EnqMfcCmd(MFC1); EnqMfcCmd(MFC1);
break; break;
case MFC_WrListStallAck:
{
if (v >= 32)
{
ConLog.Error("MFC_WrListStallAck error: invalid tag(%d)", v);
return;
}
StalledList temp = StallList[v];
if (!temp.MFCArgs)
{
ConLog.Error("MFC_WrListStallAck error: empty tag(%d)", v);
return;
}
StallList[v].MFCArgs = nullptr;
ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs);
}
break;
default: default:
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", wxString(__FUNCTION__).wx_str(), ch, wxString(spu_ch_name[ch]).wx_str()); ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", wxString(__FUNCTION__).wx_str(), ch, wxString(spu_ch_name[ch]).wx_str());
break; break;
@ -790,6 +901,10 @@ public:
while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1); while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
break; break;
case MFC_RdListStallStat:
while (!StallStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
break;
default: default:
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", wxString(__FUNCTION__).wx_str(), ch, wxString(spu_ch_name[ch]).wx_str()); ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", wxString(__FUNCTION__).wx_str(), ch, wxString(spu_ch_name[ch]).wx_str());
break; break;

View file

@ -226,7 +226,6 @@ vfsDevice* VFS::GetDevice(const wxString& ps3_path, wxString& path) const
} }
if(max_i < 0) return nullptr; if(max_i < 0) return nullptr;
path = vfsDevice::GetWinPath(m_devices[max_i].GetLocalPath(), ps3_path(max_eq, ps3_path.Len() - max_eq)); path = vfsDevice::GetWinPath(m_devices[max_i].GetLocalPath(), ps3_path(max_eq, ps3_path.Len() - max_eq));
return &m_devices[max_i]; return &m_devices[max_i];
} }
@ -303,27 +302,27 @@ void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
{ {
int idx; int idx;
idx = res.Move(new VFSManagerEntry()); idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(EmulatorDir)\\dev_hdd0\\"; res[idx].path = "$(EmulatorDir)/dev_hdd0/";
res[idx].mount = "/dev_hdd0/"; res[idx].mount = "/dev_hdd0/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(EmulatorDir)\\dev_hdd1\\"; res[idx].path = "$(EmulatorDir)/dev_hdd1/";
res[idx].mount = "/dev_hdd1/"; res[idx].mount = "/dev_hdd1/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(EmulatorDir)\\dev_flash\\"; res[idx].path = "$(EmulatorDir)/dev_flash/";
res[idx].mount = "/dev_flash/"; res[idx].mount = "/dev_flash/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(EmulatorDir)\\dev_usb000\\"; res[idx].path = "$(EmulatorDir)/dev_usb000/";
res[idx].mount = "/dev_usb000/"; res[idx].mount = "/dev_usb000/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(EmulatorDir)\\dev_usb000\\"; res[idx].path = "$(EmulatorDir)/dev_usb000/";
res[idx].mount = "/dev_usb/"; res[idx].mount = "/dev_usb/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
@ -333,7 +332,7 @@ void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(GameDir)\\..\\"; res[idx].path = "$(GameDir)/../";
res[idx].mount = "/dev_bdvd/"; res[idx].mount = "/dev_bdvd/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;

View file

@ -48,8 +48,8 @@ u32 vfsDevice::CmpLocalPath(const wxString& local_path)
wxFileName path0(m_local_path); wxFileName path0(m_local_path);
path0.Normalize(); path0.Normalize();
wxArrayString arr0 = wxSplit(path0.GetFullPath(), '\\'); wxArrayString arr0 = wxSplit(path0.GetFullPath(), '/');
wxArrayString arr1 = wxSplit(local_path, '\\'); wxArrayString arr1 = wxSplit(local_path, '/');
const u32 lim = min(arr0.GetCount(), arr1.GetCount()); const u32 lim = min(arr0.GetCount(), arr1.GetCount());
u32 ret = 0; u32 ret = 0;
@ -168,7 +168,7 @@ wxString vfsDevice::GetWinPath(const wxString& p, bool is_dir)
{ {
if(!is_ls) if(!is_ls)
{ {
ret += '\\'; ret += '/';
is_ls = true; is_ls = true;
} }
@ -179,7 +179,7 @@ wxString vfsDevice::GetWinPath(const wxString& p, bool is_dir)
ret += p[i]; ret += p[i];
} }
if(is_dir && ret[ret.Len() - 1] != '\\') ret += '\\'; if(is_dir && ret[ret.Len() - 1] != '/') ret += '/';
wxFileName res(ret); wxFileName res(ret);
res.Normalize(); res.Normalize();
@ -191,7 +191,7 @@ wxString vfsDevice::GetWinPath(const wxString& l, const wxString& r)
if(l.IsEmpty()) return GetWinPath(r, false); if(l.IsEmpty()) return GetWinPath(r, false);
if(r.IsEmpty()) return GetWinPath(l); if(r.IsEmpty()) return GetWinPath(l);
return GetWinPath(l + '\\' + r, false); return GetWinPath(l + '/' + r, false);
} }
wxString vfsDevice::GetPs3Path(const wxString& p, bool is_dir) wxString vfsDevice::GetPs3Path(const wxString& p, bool is_dir)

View file

@ -56,7 +56,7 @@ bool vfsLocalFile::Create(const wxString& path)
for(uint p=1; p < path.Len() && path[p] != '\0' ; p++) for(uint p=1; p < path.Len() && path[p] != '\0' ; p++)
{ {
for(; p < path.Len() && path[p] != '\0'; p++) for(; p < path.Len() && path[p] != '\0'; p++)
if(path[p] == '\\') break; if(path[p] == '/') break;
if(p == path.Len() || path[p] == '\0') if(p == path.Len() || path[p] == '\0')
break; break;
@ -70,7 +70,7 @@ bool vfsLocalFile::Create(const wxString& path)
} }
//create file //create file
if(path(path.Len() - 1, 1) != '\\' && !wxFileExists(path)) if(path(path.Len() - 1, 1) != '/' && !wxFileExists(path))
{ {
wxFile f; wxFile f;
return f.Create(path); return f.Create(path);

View file

@ -5,7 +5,7 @@ void GLFragmentDecompilerThread::AddCode(std::string code, bool append_mask)
{ {
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return; if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return;
const std::string mask = GetMask().c_str(); const std::string mask = GetMask();
std::string cond; std::string cond;
if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq) if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq)
@ -227,7 +227,7 @@ std::string GLFragmentDecompilerThread::BuildCode()
main += "\t" + m_parr.AddParam(PARAM_OUT, "vec4", "ocol", 0) + " = " + (m_ctrl & 0x40 ? "r0" : "h0") + ";\n"; main += "\t" + m_parr.AddParam(PARAM_OUT, "vec4", "ocol", 0) + " = " + (m_ctrl & 0x40 ? "r0" : "h0") + ";\n";
if(m_ctrl & 0xe) main += "\tgl_FragDepth = r1.z;\n"; if(m_ctrl & 0xe) main += "\tgl_FragDepth = r1.z;\n";
std::string p = ""; std::string p;
for(u32 i=0; i<m_parr.params.GetCount(); ++i) for(u32 i=0; i<m_parr.params.GetCount(); ++i)
{ {

View file

@ -2,7 +2,6 @@
#include "GLGSRender.h" #include "GLGSRender.h"
#include "Emu/Cell/PPCInstrTable.h" #include "Emu/Cell/PPCInstrTable.h"
#include "Gui/RSXDebugger.h" #include "Gui/RSXDebugger.h"
#include "OpenGL.h"
#define CMD_DEBUG 0 #define CMD_DEBUG 0
#define DUMP_VERTEX_DATA 0 #define DUMP_VERTEX_DATA 0
@ -376,33 +375,24 @@ bool GLGSRender::LoadProgram()
if(!m_cur_shader_prog) if(!m_cur_shader_prog)
{ {
ConLog.Warning("LoadProgram: m_cur_shader_prog == NULL"); ConLog.Warning("LoadProgram: m_cur_shader_prog == NULL");
return false; return false;
} }
m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_shader_prog, m_shader_prog);
if(m_fp_buf_num == -1) m_shader_prog.Decompile(*m_cur_shader_prog);
if(!m_cur_vertex_prog) if(!m_cur_vertex_prog)
{ {
ConLog.Warning("LoadProgram: m_cur_vertex_prog == NULL"); ConLog.Warning("LoadProgram: m_cur_vertex_prog == NULL");
return false; return false;
} }
//ConLog.Write("Create program"); m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_shader_prog, m_shader_prog);
m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog); m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog);
if(m_vp_buf_num == -1) //ConLog.Write("Create program");
{
ConLog.Warning("VP not found in buffer!");
m_vertex_prog.Decompile(*m_cur_vertex_prog);
}
if(m_fp_buf_num == -1) if(m_fp_buf_num == -1)
{ {
ConLog.Warning("FP not found in buffer!"); ConLog.Warning("FP not found in buffer!");
m_shader_prog.Decompile(*m_cur_shader_prog);
m_shader_prog.Wait(); m_shader_prog.Wait();
m_shader_prog.Compile(); m_shader_prog.Compile();
checkForGlError("m_shader_prog.Compile"); checkForGlError("m_shader_prog.Compile");
@ -413,6 +403,8 @@ bool GLGSRender::LoadProgram()
if(m_vp_buf_num == -1) if(m_vp_buf_num == -1)
{ {
ConLog.Warning("VP not found in buffer!");
m_vertex_prog.Decompile(*m_cur_vertex_prog);
m_vertex_prog.Wait(); m_vertex_prog.Wait();
m_vertex_prog.Compile(); m_vertex_prog.Compile();
checkForGlError("m_vertex_prog.Compile"); checkForGlError("m_vertex_prog.Compile");
@ -650,10 +642,11 @@ void GLGSRender::OnInitThread()
#ifdef _WIN32 #ifdef _WIN32
glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0); glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0);
#else // Undefined reference: glXSwapIntervalEXT
/*#else
if (GLXDrawable drawable = glXGetCurrentDrawable()){ if (GLXDrawable drawable = glXGetCurrentDrawable()){
glXSwapIntervalEXT(glXGetCurrentDisplay(), drawable, Ini.GSVSyncEnable.GetValue() ? 1 : 0); glXSwapIntervalEXT(glXGetCurrentDisplay(), drawable, Ini.GSVSyncEnable.GetValue() ? 1 : 0);
} }*/
#endif #endif
glGenTextures(1, &g_depth_tex); glGenTextures(1, &g_depth_tex);
glGenTextures(1, &g_flip_tex); glGenTextures(1, &g_flip_tex);

View file

@ -1,11 +1,9 @@
#pragma once #pragma once
#include "Emu/GS/GSRender.h" #include "Emu/GS/GSRender.h"
#include "Emu/GS/RSXThread.h" #include "Emu/GS/RSXThread.h"
#include <wx/glcanvas.h>
#include "GLBuffers.h" #include "GLBuffers.h"
#include "GLProgram.h"
#include "OpenGL.h"
#include "GLProgramBuffer.h" #include "GLProgramBuffer.h"
#include <wx/glcanvas.h>
#pragma comment(lib, "opengl32.lib") #pragma comment(lib, "opengl32.lib")
@ -304,7 +302,7 @@ public:
void Save(RSXTexture& tex) void Save(RSXTexture& tex)
{ {
static const wxString& dir_path = "textures"; static const wxString& dir_path = "textures";
static const wxString& file_fmt = dir_path + "\\" + "tex[%d].png"; static const wxString& file_fmt = dir_path + "/" + "tex[%d].png";
if(!wxDirExists(dir_path)) wxMkdir(dir_path); if(!wxDirExists(dir_path)) wxMkdir(dir_path);

View file

@ -319,7 +319,8 @@ wxString GLVertexDecompilerThread::BuildCode()
wxString f = wxEmptyString; wxString f = wxEmptyString;
f += wxString::Format("void %s()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n%s\tgl_Position = gl_Position * scaleOffsetMat;\n}\n", m_funcs[0].name.wx_str(), BuildFuncBody(m_funcs[0]).wx_str()); f += wxString::Format("void %s()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n\t%s();\n\tgl_Position = gl_Position * scaleOffsetMat;\n}\n",
m_funcs[0].name.wx_str(), m_funcs[1].name.wx_str());
for(uint i=1; i<m_funcs.GetCount(); ++i) for(uint i=1; i<m_funcs.GetCount(); ++i)
{ {
@ -354,6 +355,11 @@ void GLVertexDecompilerThread::Task()
src[2].src2l = d3.src2l; src[2].src2l = d3.src2l;
src[2].src2h = d2.src2h; src[2].src2h = d2.src2h;
if(!d1.sca_opcode && !d1.vec_opcode)
{
m_body.Add("//nop");
}
switch(d1.sca_opcode) switch(d1.sca_opcode)
{ {
case 0x00: break; // NOP case 0x00: break; // NOP
@ -364,11 +370,11 @@ void GLVertexDecompilerThread::Task()
case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP
case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG
//case 0x07: break; // LIT //case 0x07: break; // LIT
case 0x08: AddScaCode("{ /*BRA*/ " + GetFunc() + "; " + wxString(m_funcs.GetCount() == 1 || m_funcs[1].offset > intsCount ? "gl_Position = gl_Position * scaleOffsetMat;" : "") + " return; }", false, true); break; // BRA case 0x08: AddScaCode("{ /*BRA*/ " + GetFunc() + "; return; }", false, true); break; // BRA
case 0x09: AddScaCode("{ " + GetFunc() + "; " + wxString(m_funcs.GetCount() == 1 || m_funcs[1].offset > intsCount ? "gl_Position = gl_Position * scaleOffsetMat;" : "") + " return; }", false, true); break; // BRI : works differently (BRI o[1].x(TR) L0;) case 0x09: AddScaCode("{ " + GetFunc() + "; return; }", false, true); break; // BRI : works differently (BRI o[1].x(TR) L0;)
case 0x0a: AddScaCode("/*CAL*/ " + GetFunc(), false, true); break; // CAL : works same as BRI case 0x0a: AddScaCode("/*CAL*/ " + GetFunc(), false, true); break; // CAL : works same as BRI
case 0x0b: AddScaCode("/*CLI*/ " + GetFunc(), false, true); break; // CLI : works same as BRI case 0x0b: AddScaCode("/*CLI*/ " + GetFunc(), false, true); break; // CLI : works same as BRI
case 0x0c: AddScaCode("{ " + wxString(m_funcs.GetCount() == 1 || m_funcs[1].offset > intsCount ? "gl_Position = gl_Position * scaleOffsetMat;" : "") + "return; }", false, true); break; // RET : works like BRI but shorter (RET o[1].x(TR);) case 0x0c: AddScaCode("return", false, true); break; // RET : works like BRI but shorter (RET o[1].x(TR);)
case 0x0d: AddScaCode("log2(" + GetSRC(2, true) + ")"); break; // LG2 case 0x0d: AddScaCode("log2(" + GetSRC(2, true) + ")"); break; // LG2
case 0x0e: AddScaCode("exp2(" + GetSRC(2, true) + ")"); break; // EX2 case 0x0e: AddScaCode("exp2(" + GetSRC(2, true) + ")"); break; // EX2
case 0x0f: AddScaCode("sin(" + GetSRC(2, true) + ")"); break; // SIN case 0x0f: AddScaCode("sin(" + GetSRC(2, true) + ")"); break; // SIN
@ -429,7 +435,7 @@ void GLVertexDecompilerThread::Task()
m_shader = BuildCode(); m_shader = BuildCode();
m_body.Clear(); m_body.Clear();
m_funcs.RemoveAt(1, m_funcs.GetCount() - 1); m_funcs.RemoveAt(2, m_funcs.GetCount() - 2);
} }
GLVertexProgram::GLVertexProgram() GLVertexProgram::GLVertexProgram()

View file

@ -151,6 +151,9 @@ struct GLVertexDecompilerThread : public ThreadBase
m_funcs.Add(new FuncInfo()); m_funcs.Add(new FuncInfo());
m_funcs[0].offset = 0; m_funcs[0].offset = 0;
m_funcs[0].name = "main"; m_funcs[0].name = "main";
m_funcs.Add(new FuncInfo());
m_funcs[1].offset = 0;
m_funcs[1].name = "func0";
//m_cur_func->body = "\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"; //m_cur_func->body = "\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n";
} }

View file

@ -1,4 +1,7 @@
#pragma once #pragma once
#ifndef _WIN32
#include <GL/glew.h>
#endif
#include <GL/gl.h> #include <GL/gl.h>
#include "GL/glext.h" #include "GL/glext.h"

View file

@ -3,12 +3,12 @@
RSXTexture::RSXTexture() RSXTexture::RSXTexture()
{ {
m_index = 0; m_index = 0;
} }
RSXTexture::RSXTexture(u8 index) RSXTexture::RSXTexture(u8 index)
{ {
m_index = index; m_index = index;
} }
void RSXTexture::Init() void RSXTexture::Init()
@ -38,6 +38,9 @@ void RSXTexture::Init()
// Image Rect // Image Rect
methodRegisters[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index*32)] = (/*height*/1) | ((/*width*/1) << 16); methodRegisters[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index*32)] = (/*height*/1) | ((/*width*/1) << 16);
// Border Color
methodRegisters[NV4097_SET_TEXTURE_BORDER_COLOR + (m_index*32)] = 0;
} }
u32 RSXTexture::GetOffset() const u32 RSXTexture::GetOffset() const
@ -195,6 +198,11 @@ u16 RSXTexture::GetHeight() const
return ((methodRegisters[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index*32)]) & 0xffff); return ((methodRegisters[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index*32)]) & 0xffff);
} }
u32 RSXTexture::GetBorderColor() const
{
return methodRegisters[NV4097_SET_TEXTURE_BORDER_COLOR + (m_index*32)];
}
void RSXTexture::SetControl3(u16 depth, u32 pitch) void RSXTexture::SetControl3(u16 depth, u32 pitch)
{ {
m_depth = depth; m_depth = depth;

View file

@ -58,5 +58,8 @@ public:
u16 GetWidth() const; u16 GetWidth() const;
u16 GetHeight() const; u16 GetHeight() const;
// Border Color
u32 GetBorderColor() const;
void SetControl3(u16 depth, u32 pitch); void SetControl3(u16 depth, u32 pitch);
}; };

View file

@ -322,6 +322,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
} }
break; break;
case_16(NV4097_SET_TEXTURE_BORDER_COLOR,0x20):
{
}
case NV4097_SET_SURFACE_FORMAT: case NV4097_SET_SURFACE_FORMAT:
{ {
u32 a0 = ARGS(0); u32 a0 = ARGS(0);
@ -333,29 +337,13 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
m_surface_width = (a0 >> 16) & 0xff; m_surface_width = (a0 >> 16) & 0xff;
m_surface_height = (a0 >> 24) & 0xff; m_surface_height = (a0 >> 24) & 0xff;
if(count >= 2) switch (min((u32)6, count))
{ {
m_surface_pitch_a = ARGS(1); case 6: m_surface_pitch_b = ARGS(5);
case 5: m_surface_offset_b = ARGS(4);
if(count >= 3) case 4: m_surface_offset_z = ARGS(3);
{ case 3: m_surface_offset_a = ARGS(2);
m_surface_offset_a = ARGS(2); case 2: m_surface_pitch_a = ARGS(1);
if(count >= 4)
{
m_surface_offset_z = ARGS(3);
if(count >= 5)
{
m_surface_offset_b = ARGS(4);
if(count >= 6)
{
m_surface_pitch_b = ARGS(5);
}
}
}
}
} }
gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr); gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr);

View file

@ -695,7 +695,7 @@ public:
do do
{ {
if(s[pos] == '\\' || s[pos] == '\0') if(s[pos] == '/' || s[pos] == '\0')
{ {
if(file_pos != -1) if(file_pos != -1)
{ {

View file

@ -513,6 +513,8 @@ public:
__forceinline AT GetAddr() const { return m_addr; } __forceinline AT GetAddr() const { return m_addr; }
__forceinline void SetAddr(AT addr) { m_addr = addr; }
__forceinline bool IsGood() const __forceinline bool IsGood() const
{ {
return Memory.IsGoodAddr(m_addr, sizeof(T)); return Memory.IsGoodAddr(m_addr, sizeof(T));

View file

@ -63,7 +63,7 @@ static const g_module_list[] =
{0x002e, "cellLv2dbg"}, {0x002e, "cellLv2dbg"},
{0x0030, "cellUsbpspcm"}, {0x0030, "cellUsbpspcm"},
{0x0031, "cellAvconfExt"}, {0x0031, "cellAvconfExt"},
{0x0032, "cellSysutilUserinfo"}, {0x0032, "cellUserInfo"},
{0x0033, "cellSysutilSavedata"}, {0x0033, "cellSysutilSavedata"},
{0x0034, "cellSubdisplay"}, {0x0034, "cellSubdisplay"},
{0x0035, "cellSysutilRec"}, {0x0035, "cellSysutilRec"},

View file

@ -20,14 +20,66 @@ int adecRead(void* opaque, u8* buf, int buf_size)
{ {
AudioDecoder& adec = *(AudioDecoder*)opaque; AudioDecoder& adec = *(AudioDecoder*)opaque;
if (adec.reader.size < (u32)buf_size) int res = 0;
next:
if (adec.reader.size < (u32)buf_size /*&& !adec.just_started*/)
{
while (adec.job.IsEmpty())
{
if (Emu.IsStopped())
{
ConLog.Warning("adecRead() aborted");
return 0;
}
Sleep(1);
}
switch (adec.job.Peek().type)
{
case adecEndSeq:
{
buf_size = adec.reader.size;
}
break;
case adecDecodeAu:
{
if (!Memory.CopyToReal(buf, adec.reader.addr, adec.reader.size))
{
ConLog.Error("adecRead: data reading failed (reader.size=0x%x)", adec.reader.size);
Emu.Pause();
return 0;
}
buf += adec.reader.size;
buf_size -= adec.reader.size;
res += adec.reader.size;
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
adec.job.Pop(adec.task);
adec.reader.addr = adec.task.au.addr;
adec.reader.size = adec.task.au.size;
adec.last_pts = adec.task.au.pts;
}
break;
default:
ConLog.Error("adecRead(): sequence error (task %d)", adec.job.Peek().type);
return 0;
}
goto next;
}
else if (adec.reader.size < (u32)buf_size)
{ {
buf_size = adec.reader.size; buf_size = adec.reader.size;
} }
if (!buf_size) if (!buf_size)
{ {
return 0; return res;
} }
else if (!Memory.CopyToReal(buf, adec.reader.addr, buf_size)) else if (!Memory.CopyToReal(buf, adec.reader.addr, buf_size))
{ {
@ -39,7 +91,7 @@ int adecRead(void* opaque, u8* buf, int buf_size)
{ {
adec.reader.addr += buf_size; adec.reader.addr += buf_size;
adec.reader.size -= buf_size; adec.reader.size -= buf_size;
return 0 + buf_size; return res + buf_size;
} }
} }
@ -59,7 +111,7 @@ u32 adecOpen(AudioDecoder* data)
{ {
ConLog.Write("Audio Decoder enter()"); ConLog.Write("Audio Decoder enter()");
AdecTask task; AdecTask& task = adec.task;
while (true) while (true)
{ {
@ -119,12 +171,12 @@ u32 adecOpen(AudioDecoder* data)
case adecDecodeAu: case adecDecodeAu:
{ {
int err; int err = 0;
adec.reader.addr = task.au.addr; adec.reader.addr = task.au.addr;
adec.reader.size = task.au.size; adec.reader.size = task.au.size;
u64 last_pts = task.au.pts; adec.last_pts = task.au.pts;
struct AVPacketHolder : AVPacket struct AVPacketHolder : AVPacket
{ {
@ -171,6 +223,13 @@ u32 adecOpen(AudioDecoder* data)
Emu.Pause(); Emu.Pause();
break; break;
} }
AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); // ???
if (!codec)
{
ConLog.Error("adecDecodeAu: avcodec_find_decoder() failed");
Emu.Pause();
break;
}
err = avformat_find_stream_info(adec.fmt, NULL); err = avformat_find_stream_info(adec.fmt, NULL);
if (err) if (err)
{ {
@ -186,15 +245,7 @@ u32 adecOpen(AudioDecoder* data)
} }
adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data
AVCodec* codec = avcodec_find_decoder(adec.ctx->codec_id); // ??? AVDictionary* opts = nullptr;
if (!codec)
{
ConLog.Error("adecDecodeAu: avcodec_find_decoder() failed");
Emu.Pause();
break;
}
AVDictionary* opts;
av_dict_set(&opts, "refcounted_frames", "1", 0); av_dict_set(&opts, "refcounted_frames", "1", 0);
{ {
SMutexGeneralLocker lock(g_mutex_avcodec_open2); SMutexGeneralLocker lock(g_mutex_avcodec_open2);
@ -208,10 +259,18 @@ u32 adecOpen(AudioDecoder* data)
break; break;
} }
adec.just_started = false; adec.just_started = false;
} }*/
while (av_read_frame(adec.fmt, &au) >= 0)*/ while (true) bool last_frame = false;
while (true)
{ {
if (Emu.IsStopped())
{
ConLog.Warning("adecDecodeAu aborted");
return;
}
if (!adec.ctx) // fake if (!adec.ctx) // fake
{ {
AdecFrame frame; AdecFrame frame;
@ -223,23 +282,28 @@ u32 adecOpen(AudioDecoder* data)
frame.data = nullptr; frame.data = nullptr;
adec.frames.Push(frame); adec.frames.Push(frame);
/*Callback cb;
cb.SetAddr(adec.cbFunc);
cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
cb.Branch(false);*/
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
break; break;
} }
struct VdecFrameHolder : AdecFrame last_frame = av_read_frame(adec.fmt, &au) < 0;
if (last_frame)
{ {
VdecFrameHolder() //break;
av_free(au.data);
au.data = NULL;
au.size = 0;
}
struct AdecFrameHolder : AdecFrame
{
AdecFrameHolder()
{ {
data = av_frame_alloc(); data = av_frame_alloc();
} }
~VdecFrameHolder() ~AdecFrameHolder()
{ {
if (data) if (data)
{ {
@ -261,15 +325,18 @@ u32 adecOpen(AudioDecoder* data)
int decode = avcodec_decode_audio4(adec.ctx, frame.data, &got_frame, &au); int decode = avcodec_decode_audio4(adec.ctx, frame.data, &got_frame, &au);
if (decode < 0) if (decode <= 0)
{ {
ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode); if (!last_frame && decode < 0)
break; {
ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode);
}
if (!got_frame && adec.reader.size == 0) break;
} }
if (got_frame) if (got_frame)
{ {
ConLog.Write("got_frame (%d, vdec: pts=0x%llx, dts=0x%llx)", got_frame, au.pts, au.dts); ConLog.Write("got_frame (%d, pts=0x%llx, dts=0x%llx)", got_frame, au.pts, au.dts);
frame.pts = task.au.pts; // ??? frame.pts = task.au.pts; // ???
frame.auAddr = task.au.addr; frame.auAddr = task.au.addr;

View file

@ -1064,6 +1064,9 @@ public:
const u32 cbArg; const u32 cbArg;
u32 memBias; u32 memBias;
AdecTask task;
u64 last_pts;
CPUThread* adecCb; CPUThread* adecCb;
AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg) AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg)

View file

@ -17,9 +17,6 @@ int cellAudioInit()
{ {
cellAudio.Warning("cellAudioInit()"); cellAudio.Warning("cellAudioInit()");
if(Ini.AudioOutMode.GetValue() == 1)
m_audio_out->Init();
if (m_config.m_is_audio_initialized) if (m_config.m_is_audio_initialized)
{ {
return CELL_AUDIO_ERROR_ALREADY_INIT; return CELL_AUDIO_ERROR_ALREADY_INIT;
@ -53,14 +50,23 @@ int cellAudioInit()
float buffer[2*256]; // buffer for 2 channels float buffer[2*256]; // buffer for 2 channels
be_t<float> buffer2[8*256]; // buffer for 8 channels (max count) be_t<float> buffer2[8*256]; // buffer for 8 channels (max count)
u16 oal_buffer[2*256]; // buffer for OpenAL //u16 oal_buffer[2*256]; // buffer for OpenAL
memset(&buffer, 0, sizeof(buffer)); uint oal_buffer_offset = 0;
memset(&buffer2, 0, sizeof(buffer2)); uint oal_buffer_size = 2 * 256;
memset(&oal_buffer, 0, sizeof(oal_buffer)); std::unique_ptr<u16[]> oal_buffer(new u16[oal_buffer_size]);
if(Ini.AudioOutMode.GetValue() == 1) memset(buffer, 0, sizeof(buffer));
m_audio_out->Open(oal_buffer, sizeof(oal_buffer)); memset(buffer2, 0, sizeof(buffer2));
memset(oal_buffer.get(), 0, oal_buffer_size * sizeof(u16));
Array<u64> keys;
if(m_audio_out)
{
m_audio_out->Init();
m_audio_out->Open(oal_buffer.get(), oal_buffer_size*sizeof(u16));
}
while (m_config.m_is_audio_initialized) while (m_config.m_is_audio_initialized)
{ {
@ -120,8 +126,10 @@ int cellAudioInit()
buffer[i] = buffer2[i]; buffer[i] = buffer2[i];
// convert the data from float to u16 // convert the data from float to u16
oal_buffer[i] = (u16)((float)buffer[i] * (1 << 16)); assert(buffer[i] >= -4.0f && buffer[i] <= 4.0f);
oal_buffer[oal_buffer_offset + i] = (u16)(buffer[i] * ((1 << 13) - 1));
} }
first_mix = false; first_mix = false;
} }
else else
@ -131,17 +139,35 @@ int cellAudioInit()
buffer[i] = (buffer[i] + buffer2[i]) * 0.5; // TODO: valid mixing buffer[i] = (buffer[i] + buffer2[i]) * 0.5; // TODO: valid mixing
// convert the data from float to u16 // convert the data from float to u16
oal_buffer[i] = (u16)((float)buffer[i] * (1 << 16)); assert(buffer[i] >= -4.0f && buffer[i] <= 4.0f);
oal_buffer[oal_buffer_offset + i] = (u16)(buffer[i] * ((1 << 13) - 1));
} }
} }
} }
// send aftermix event (normal audio event) // send aftermix event (normal audio event)
// TODO: check event source {
Emu.GetEventManager().SendEvent(m_config.event_key, 0x10103000e010e07, 0, 0, 0); std::lock_guard<std::mutex> lock(m_config.m_mutex);
keys.SetCount(m_config.m_keys.GetCount());
memcpy(keys.GetPtr(), m_config.m_keys.GetPtr(), sizeof(u64) * keys.GetCount());
}
for (u32 i = 0; i < keys.GetCount(); i++)
{
// TODO: check event source
Emu.GetEventManager().SendEvent(keys[i], 0x10103000e010e07, 0, 0, 0);
}
if(Ini.AudioOutMode.GetValue() == 1) oal_buffer_offset += sizeof(buffer) / sizeof(float);
m_audio_out->AddData(oal_buffer, sizeof(oal_buffer));
if(oal_buffer_offset >= oal_buffer_size)
{
if(m_audio_out)
{
m_audio_out->AddData(oal_buffer.get(), oal_buffer_offset * sizeof(u16));
}
oal_buffer_offset = 0;
}
if(Ini.AudioDumpToFile.GetValue()) if(Ini.AudioDumpToFile.GetValue())
{ {
@ -160,8 +186,6 @@ abort:
m_dump.Finalize(); m_dump.Finalize();
m_config.m_is_audio_finalized = true; m_config.m_is_audio_finalized = true;
if(Ini.AudioOutMode.GetValue() == 1)
m_audio_out->Quit();
}); });
t.detach(); t.detach();
@ -191,8 +215,6 @@ int cellAudioQuit()
Memory.Free(m_config.m_buffer); Memory.Free(m_config.m_buffer);
Memory.Free(m_config.m_indexes); Memory.Free(m_config.m_indexes);
if(Ini.AudioOutMode.GetValue() == 1)
m_audio_out->Quit();
return CELL_OK; return CELL_OK;
} }
@ -301,9 +323,6 @@ int cellAudioPortStart(u32 portNum)
m_config.m_ports[portNum].m_is_audio_port_started = true; m_config.m_ports[portNum].m_is_audio_port_started = true;
if(Ini.AudioOutMode.GetValue() == 1)
m_audio_out->Play();
return CELL_OK; return CELL_OK;
} }
@ -432,21 +451,27 @@ int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key)
{ {
cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr()); cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr());
if (Emu.GetEventManager().CheckKey(0x80004d494f323221)) std::lock_guard<std::mutex> lock(m_config.m_mutex);
u64 event_key = 0;
while (Emu.GetEventManager().CheckKey((event_key << 48) | 0x80004d494f323221))
{ {
return CELL_AUDIO_ERROR_EVENT_QUEUE; event_key++; // experimental
//return CELL_AUDIO_ERROR_EVENT_QUEUE;
} }
event_key = (event_key << 48) | 0x80004d494f323221; // left part: 0x8000, 0x8001, 0x8002 ...
EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0x80004d494f323221, 0x80004d494f323221, 32); EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, event_key, event_key, 32);
if (!Emu.GetEventManager().RegisterKey(eq, 0x80004d494f323221)) if (!Emu.GetEventManager().RegisterKey(eq, event_key))
{ {
delete eq; delete eq;
return CELL_AUDIO_ERROR_EVENT_QUEUE; return CELL_AUDIO_ERROR_EVENT_QUEUE;
} }
m_config.m_keys.AddCpy(event_key);
id = cellAudio.GetNewId(eq); id = cellAudio.GetNewId(eq);
key = 0x80004d494f323221; key = event_key;
return CELL_OK; return CELL_OK;
} }
@ -461,7 +486,9 @@ int cellAudioSetNotifyEventQueue(u64 key)
{ {
cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key); cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key);
m_config.event_key = key; std::lock_guard<std::mutex> lock(m_config.m_mutex);
m_config.m_keys.AddCpy(key);
/*EventQueue* eq; /*EventQueue* eq;
if (!Emu.GetEventManager().GetEventQueue(key, eq)) if (!Emu.GetEventManager().GetEventQueue(key, eq))
@ -484,13 +511,30 @@ int cellAudioRemoveNotifyEventQueue(u64 key)
{ {
cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key); cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key);
EventQueue* eq; std::lock_guard<std::mutex> lock(m_config.m_mutex);
if (!Emu.GetEventManager().GetEventQueue(key, eq))
bool found = false;
for (u32 i = 0; i < m_config.m_keys.GetCount(); i++)
{ {
if (m_config.m_keys[i] == key)
{
m_config.m_keys.RemoveAt(i);
found = true;
break;
}
}
if (!found)
{
// ???
return CELL_AUDIO_ERROR_PARAM; return CELL_AUDIO_ERROR_PARAM;
} }
m_config.event_key = 0; /*EventQueue* eq;
if (!Emu.GetEventManager().GetEventQueue(key, eq))
{
return CELL_AUDIO_ERROR_PARAM;
}*/
// TODO: disconnect port // TODO: disconnect port

View file

@ -18,7 +18,7 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t<CellCodecEsFi
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr) const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
{ {
if (esFilterId->filterIdMajor >= 0xe0) if (esFilterId->filterIdMajor >= 0xe0)
attr->memSize = 0x1000000; // 0x45fa49 from ps3 attr->memSize = 0x3000000; // 0x45fa49 from ps3
else else
attr->memSize = 0x200000; // 0x73d9 from ps3 attr->memSize = 0x200000; // 0x73d9 from ps3
@ -156,6 +156,16 @@ u32 dmuxOpen(Demuxer* data)
//ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); //ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts);
stream.skip(4);
len -= 4;
u32 abc;
stream.peek(abc);
if (abc == 0x5548D00F)
{
stream.skip(8);
len -= 8;
}
es.push(stream, len - pes.size - 3, pes); es.push(stream, len - pes.size - 3, pes);
es.finish(stream); es.finish(stream);
@ -231,7 +241,7 @@ u32 dmuxOpen(Demuxer* data)
continue; continue;
} }
//hack: reconstruction of MPEG2-PS stream for vdec module (seems it works without it too) //reconstruction of MPEG2-PS stream for vdec module
stream = backup; stream = backup;
es.push(stream, len + 6 /*- pes.size - 3*/, pes); es.push(stream, len + 6 /*- pes.size - 3*/, pes);
} }
@ -288,18 +298,32 @@ u32 dmuxOpen(Demuxer* data)
{ {
case dmuxSetStream: case dmuxSetStream:
{ {
if (stream.discontinuity)
{
for (u32 i = 0; i < 192; i++)
{
if (esALL[i])
{
esALL[i]->reset();
}
}
updates_count = 0;
updates_signaled = 0;
}
if (updates_count != updates_signaled)
{
ConLog.Error("dmuxSetStream: stream update inconsistency (input=%d, signaled=%d)", updates_count, updates_signaled);
return;
}
updates_count++;
stream = task.stream; stream = task.stream;
ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)", ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)",
stream.addr, stream.size, stream.discontinuity, stream.userdata); stream.addr, stream.size, stream.discontinuity, stream.userdata);
if (stream.discontinuity) for (u32 i = 0; i < 192; i++)
{
if (esALL[i])
{
esALL[i]->reset();
}
}
updates_count++;
dmux.is_running = true; dmux.is_running = true;
dmux.fbSetStream.Push(task.stream.addr); // feedback
} }
break; break;
@ -592,12 +616,12 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
return CELL_DMUX_ERROR_FATAL; return CELL_DMUX_ERROR_FATAL;
} }
while (dmux->is_running) // !!! if (dmux->is_running)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
ConLog.Warning("cellDmuxSetStream(%d) aborted (waiting)", demuxerHandle); ConLog.Warning("cellDmuxSetStream(%d) aborted (waiting)", demuxerHandle);
break; return CELL_OK;
} }
Sleep(1); Sleep(1);
return CELL_DMUX_ERROR_BUSY; return CELL_DMUX_ERROR_BUSY;
@ -612,14 +636,16 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
dmux->job.Push(task); dmux->job.Push(task);
while (!dmux->is_running) u32 addr;
if (!dmux->fbSetStream.Pop(addr))
{ {
if (Emu.IsStopped()) ConLog.Warning("cellDmuxSetStream(%d) aborted (fbSetStream.Pop())", demuxerHandle);
{ return CELL_OK;
ConLog.Warning("cellDmuxSetStream(%d) aborted", demuxerHandle); }
break; if (addr != info.addr)
} {
Sleep(1); ConLog.Error("cellDmuxSetStream(%d): wrong stream queued (right=0x%x, queued=0x%x)", demuxerHandle, info.addr, addr);
Emu.Pause();
} }
return CELL_OK; return CELL_OK;
} }
@ -921,7 +947,7 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_
int cellDmuxReleaseAu(u32 esHandle) int cellDmuxReleaseAu(u32 esHandle)
{ {
cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle); cellDmux.Log("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
return CELL_OK; return CELL_OK;
@ -931,21 +957,8 @@ int cellDmuxReleaseAu(u32 esHandle)
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
if (!es->canrelease())
{
cellDmux.Error("cellDmuxReleaseAu: no AU");
return CELL_DMUX_ERROR_SEQ;
}
/*DemuxerTask task(dmuxReleaseAu);
task.es.es = esHandle;
task.es.es_ptr = es;
es->dmux->job.Push(task);*/
if (!es->release()) if (!es->release())
{ {
cellDmux.Error("cellDmuxReleaseAu failed");
return CELL_DMUX_ERROR_SEQ; return CELL_DMUX_ERROR_SEQ;
} }
return CELL_OK; return CELL_OK;
@ -953,7 +966,7 @@ int cellDmuxReleaseAu(u32 esHandle)
int cellDmuxFlushEs(u32 esHandle) int cellDmuxFlushEs(u32 esHandle)
{ {
cellDmux.Log("cellDmuxFlushEs(esHandle=0x%x)", esHandle); cellDmux.Warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle);
ElementaryStream* es; ElementaryStream* es;
if (!Emu.GetIdManager().GetIDData(esHandle, es)) if (!Emu.GetIdManager().GetIDData(esHandle, es))

View file

@ -304,11 +304,6 @@ enum
PRIVATE_STREAM_2 = 0x000001bf, PRIVATE_STREAM_2 = 0x000001bf,
}; };
enum
{
MAX_AU = 640 * 1024 + 128, // 640 KB
};
struct DemuxerStream struct DemuxerStream
{ {
u32 addr; u32 addr;
@ -385,7 +380,7 @@ struct PesHeader
stream.get(v); stream.get(v);
if (v != 0xFF) break; // skip padding bytes if (v != 0xFF) break; // skip padding bytes
empty++; empty++;
if (empty = size) return; if (empty == size) return;
}; };
if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only
@ -460,7 +455,8 @@ struct DemuxerTask
class Demuxer class Demuxer
{ {
public: public:
SQueue<DemuxerTask> job; SQueue<DemuxerTask, 32> job;
SQueue<u32, 16> fbSetStream;
const u32 memAddr; const u32 memAddr;
const u32 memSize; const u32 memSize;
const u32 cbFunc; const u32 cbFunc;
@ -492,6 +488,26 @@ class ElementaryStream
u32 last_size; // number of bytes written (after 128b header) u32 last_size; // number of bytes written (after 128b header)
u32 peek_addr; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex) u32 peek_addr; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex)
bool is_full()
{
if (first_addr)
{
if (first_addr >= last_addr)
{
return (first_addr - last_addr) <= GetMaxAU();
}
else
{
// probably, always false
return (last_addr + GetMaxAU()) > (memAddr + memSize);
}
}
else
{
return false;
}
}
public: public:
Demuxer* dmux; Demuxer* dmux;
u32 id; u32 id;
@ -523,6 +539,11 @@ public:
{ {
} }
const u32 GetMaxAU() const
{
return 640 * 1024 + 128;
}
volatile bool hasunseen() volatile bool hasunseen()
{ {
return peek_addr; return peek_addr;
@ -536,21 +557,7 @@ public:
bool isfull() bool isfull()
{ {
SMutexLocker lock(mutex); SMutexLocker lock(mutex);
if (first_addr) return is_full();
{
if (first_addr > last_addr)
{
return (first_addr - last_addr) < MAX_AU;
}
else
{
return (first_addr + MAX_AU) > (memAddr + memSize);
}
}
else
{
return false;
}
} }
void finish(DemuxerStream& stream) // not multithread-safe void finish(DemuxerStream& stream) // not multithread-safe
@ -565,8 +572,9 @@ public:
{ {
peek_addr = last_addr; peek_addr = last_addr;
} }
u32 new_addr = a128(last_addr + 128 + last_size); u32 new_addr = a128(last_addr + 128 + last_size);
if ((new_addr + MAX_AU) > (memAddr + memSize)) if ((new_addr + GetMaxAU()) > (memAddr + memSize))
{ {
last_addr = memAddr; last_addr = memAddr;
} }
@ -581,24 +589,8 @@ public:
{ {
SMutexLocker lock(mutex); SMutexLocker lock(mutex);
//ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); //ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
bool is_full;
if (first_addr)
{
if (first_addr > last_addr)
{
is_full = (first_addr - last_addr) < MAX_AU;
}
else
{
is_full = (first_addr + MAX_AU) > (memAddr + memSize);
}
}
else
{
is_full = false;
}
if (is_full) if (is_full())
{ {
ConLog.Error("ElementaryStream::push(): buffer is full"); ConLog.Error("ElementaryStream::push(): buffer is full");
Emu.Pause(); Emu.Pause();
@ -646,16 +638,11 @@ public:
} }
} }
volatile bool canrelease()
{
return first_addr;
}
bool release() bool release()
{ {
SMutexLocker lock(mutex); SMutexLocker lock(mutex);
//ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); //ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
if (!canrelease()) if (!first_addr)
{ {
ConLog.Error("ElementaryStream::release(): buffer is empty"); ConLog.Error("ElementaryStream::release(): buffer is empty");
return false; return false;
@ -675,7 +662,7 @@ public:
{ {
first_addr = 0; first_addr = 0;
} }
else if ((new_addr + MAX_AU) > (memAddr + memSize)) else if ((new_addr + GetMaxAU()) > (memAddr + memSize))
{ {
first_addr = memAddr; first_addr = memAddr;
} }
@ -706,7 +693,7 @@ public:
{ {
peek_addr = 0; peek_addr = 0;
} }
else if ((new_addr + MAX_AU) > (memAddr + memSize)) else if ((new_addr + GetMaxAU()) > (memAddr + memSize))
{ {
peek_addr = memAddr; peek_addr = memAddr;
} }

View file

@ -459,6 +459,9 @@ void cellFontRenderSurfaceInit(mem_ptr_t<CellFontRenderSurface> surface, u32 buf
surface->pixelSizeByte = pixelSizeByte; surface->pixelSizeByte = pixelSizeByte;
surface->width = w; surface->width = w;
surface->height = h; surface->height = h;
if (!buffer_addr)
surface->buffer_addr = Memory.Alloc(bufferWidthByte * h, 1); // TODO: Huge memory leak
} }
void cellFontRenderSurfaceSetScissor(mem_ptr_t<CellFontRenderSurface> surface, s32 x0, s32 y0, s32 w, s32 h) void cellFontRenderSurfaceSetScissor(mem_ptr_t<CellFontRenderSurface> surface, s32 x0, s32 y0, s32 w, s32 h)

View file

@ -116,15 +116,24 @@ int cellGameBootCheck(mem32_t type, mem32_t attributes, mem_ptr_t<CellGameConten
type.GetAddr(), attributes.GetAddr(), size.GetAddr(), dirName.GetAddr()); type.GetAddr(), attributes.GetAddr(), size.GetAddr(), dirName.GetAddr());
if (!type.IsGood() || !attributes.IsGood() || !size.IsGood() || !dirName.IsGood()) if (!type.IsGood() || !attributes.IsGood() || !size.IsGood() || !dirName.IsGood())
{
cellGame.Warning("cellGameBootCheck returns CELL_GAME_ERROR_PARAM. As a result size->hddFreeSizeKB may be 0.");
return CELL_GAME_ERROR_PARAM; return CELL_GAME_ERROR_PARAM;
}
wxString dir = wxEmptyString; // TODO: Only works for HDD games
type = CELL_GAME_GAMETYPE_HDD;
type = CELL_GAME_GAMETYPE_DISC;
attributes = 0; attributes = 0;
size->hddFreeSizeKB = 40000000; //40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run. size->hddFreeSizeKB = 40000000; //40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run.
size->sizeKB = CELL_GAME_SIZEKB_NOTCALC; size->sizeKB = CELL_GAME_SIZEKB_NOTCALC;
size->sysSizeKB = 0; size->sysSizeKB = 0;
// TODO: Locate the PARAM.SFO. The following path may be wrong.
vfsFile f("/app_home/PARAM.SFO");
PSFLoader psf(f);
if(!psf.Load(false))
return CELL_GAME_ERROR_FAILURE;
wxString dir = psf.m_info.serial(0,4) + psf.m_info.serial(5,5);
Memory.WriteString(dirName.GetAddr(), dir); Memory.WriteString(dirName.GetAddr(), dir);
return CELL_OK; return CELL_OK;
@ -150,6 +159,16 @@ int cellGameContentPermit(mem_list_ptr_t<u8> contentInfoPath, mem_list_ptr_t<u8
if (!contentInfoPath.IsGood() || !usrdirPath.IsGood()) if (!contentInfoPath.IsGood() || !usrdirPath.IsGood())
return CELL_GAME_ERROR_PARAM; return CELL_GAME_ERROR_PARAM;
// TODO: Locate the PARAM.SFO. The following path may be wrong.
vfsFile f("/app_home/PARAM.SFO");
PSFLoader psf(f);
if(!psf.Load(false))
return CELL_GAME_ERROR_FAILURE;
wxString title_id = psf.m_info.serial(0,4) + psf.m_info.serial(5,5);
// TODO: Only works for HDD games
Memory.WriteString(contentInfoPath.GetAddr(), "/dev_hdd0/game/"+title_id);
Memory.WriteString(usrdirPath.GetAddr(), "/dev_hdd0/game/"+title_id+"/USRDIR");
return CELL_OK; return CELL_OK;
} }
@ -172,7 +191,7 @@ int cellGameGetParamInt(u32 id, mem32_t value)
if(!value.IsGood()) if(!value.IsGood())
return CELL_GAME_ERROR_PARAM; return CELL_GAME_ERROR_PARAM;
// TODO: Locate the PARAM.SFO. The following path is in most cases wrong. // TODO: Locate the PARAM.SFO. The following path may be wrong.
vfsFile f("/app_home/PARAM.SFO"); vfsFile f("/app_home/PARAM.SFO");
PSFLoader psf(f); PSFLoader psf(f);
if(!psf.Load(false)) if(!psf.Load(false))
@ -198,7 +217,7 @@ int cellGameGetParamString(u32 id, mem_list_ptr_t<u8> buf, u32 bufsize)
if(!buf.IsGood()) if(!buf.IsGood())
return CELL_GAME_ERROR_PARAM; return CELL_GAME_ERROR_PARAM;
// TODO: Locate the PARAM.SFO. The following path is in most cases wrong. // TODO: Locate the PARAM.SFO. The following path may be wrong.
vfsFile f("/app_home/PARAM.SFO"); vfsFile f("/app_home/PARAM.SFO");
PSFLoader psf(f); PSFLoader psf(f);
if(!psf.Load(false)) if(!psf.Load(false))

View file

@ -2,6 +2,11 @@
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h" #include "Emu/SysCalls/SC_FUNC.h"
// Requires GCC 4.10 apparently..
#ifdef _MSC_VER
#include <codecvt>
#endif
void cellL10n_init(); void cellL10n_init();
Module cellL10n(0x001e, cellL10n_init); Module cellL10n(0x001e, cellL10n_init);
@ -22,24 +27,19 @@ int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t
if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood()) if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood())
return SRCIllegal; return SRCIllegal;
std::wstring wstr = (wchar_t*)Memory.VirtualToRealAddr(utf16); std::u16string wstr =(char16_t*)Memory.VirtualToRealAddr(utf16);
std::string str; wstr.resize(utf16_len.GetValue()); // TODO: Is this really the role of utf16_len in this function?
#ifdef _MSC_VER
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
std::string str = convert.to_bytes(wstr);
int len = min((int)utf16_len.GetValue(), (int)wstr.size()); if (!utf8.IsGood() || utf8_len.GetValue() < str.size())
int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL); utf8_len = str.size();
if (!utf8.IsGood())
utf8_len = size;
if (utf8_len.GetValue() < size)
return DSTExhausted; return DSTExhausted;
#ifdef WIN32 utf8_len = str.size();
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &str[0], size, NULL, NULL); Memory.WriteString(utf8, str.c_str());
#else
// TODO
#endif #endif
Memory.WriteString(utf8, str);
return ConversionOK; return ConversionOK;
} }

View file

@ -9,7 +9,7 @@ Module cellSpurs(0x000a, cellSpurs_init);
int _cellSpursAttributeInitialize(mem_ptr_t<CellSpursAttribute> attr, int nSpus, int spuPriority, int _cellSpursAttributeInitialize(mem_ptr_t<CellSpursAttribute> attr, int nSpus, int spuPriority,
int ppuPriority, bool exitIfNoWork) int ppuPriority, bool exitIfNoWork)
{ {
cellSpurs.Warning("cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%u, spuPriority=%u, ppuPriority=%u, exitIfNoWork=%u)", cellSpurs.Error("_cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%u, spuPriority=%u, ppuPriority=%u, exitIfNoWork=%u)",
attr.GetAddr(), nSpus, spuPriority, ppuPriority, exitIfNoWork); attr.GetAddr(), nSpus, spuPriority, ppuPriority, exitIfNoWork);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -18,7 +18,7 @@ int _cellSpursAttributeInitialize(mem_ptr_t<CellSpursAttribute> attr, int nSpus,
int cellSpursAttributeSetMemoryContainerForSpuThread(mem_ptr_t<CellSpursAttribute> attr, u32 container) int cellSpursAttributeSetMemoryContainerForSpuThread(mem_ptr_t<CellSpursAttribute> attr, u32 container)
{ {
cellSpurs.Warning("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=0x%x)", cellSpurs.Error("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=0x%x)",
attr.GetAddr(), container); attr.GetAddr(), container);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -27,7 +27,7 @@ int cellSpursAttributeSetMemoryContainerForSpuThread(mem_ptr_t<CellSpursAttribut
int cellSpursAttributeSetNamePrefix(mem_ptr_t<CellSpursAttribute> attr, const mem8_t prefix, u32 size) int cellSpursAttributeSetNamePrefix(mem_ptr_t<CellSpursAttribute> attr, const mem8_t prefix, u32 size)
{ {
cellSpurs.Warning("cellSpursAttributeSetNamePrefix(attr_addr=0x%x, prefix_addr=0x%x, size=0x%x)", cellSpurs.Error("cellSpursAttributeSetNamePrefix(attr_addr=0x%x, prefix_addr=0x%x, size=0x%x)",
attr.GetAddr(), prefix.GetAddr(), size); attr.GetAddr(), prefix.GetAddr(), size);
if(!attr.IsGood() || !prefix.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!attr.IsGood() || !prefix.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(size > 15) return CELL_SPURS_CORE_ERROR_INVAL; if(size > 15) return CELL_SPURS_CORE_ERROR_INVAL;
@ -37,7 +37,7 @@ int cellSpursAttributeSetNamePrefix(mem_ptr_t<CellSpursAttribute> attr, const me
int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t<CellSpursAttribute> attr) int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t<CellSpursAttribute> attr)
{ {
cellSpurs.Warning("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.GetAddr()); cellSpurs.Error("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.GetAddr());
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK; return CELL_OK;
@ -45,7 +45,7 @@ int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t<CellSpursAttribute> a
int cellSpursAttributeSetSpuThreadGroupType(mem_ptr_t<CellSpursAttribute> attr, int type) int cellSpursAttributeSetSpuThreadGroupType(mem_ptr_t<CellSpursAttribute> attr, int type)
{ {
cellSpurs.Warning("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%u)", attr.GetAddr(), type); cellSpurs.Error("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%u)", attr.GetAddr(), type);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK; return CELL_OK;
@ -54,10 +54,10 @@ int cellSpursAttributeSetSpuThreadGroupType(mem_ptr_t<CellSpursAttribute> attr,
int cellSpursAttributeEnableSystemWorkload(mem_ptr_t<CellSpursAttribute> attr, const u8 priority[8], int cellSpursAttributeEnableSystemWorkload(mem_ptr_t<CellSpursAttribute> attr, const u8 priority[8],
uint maxSpu, const bool isPreemptible[8]) uint maxSpu, const bool isPreemptible[8])
{ {
cellSpurs.Warning("cellSpursAttributeEnableSystemWorkload(attr_addr=0x%x, priority[%u], maxSpu=%u, isPreemptible[%u])", cellSpurs.Error("cellSpursAttributeEnableSystemWorkload(attr_addr=0x%x, priority[%u], maxSpu=%u, isPreemptible[%u])",
attr.GetAddr(), priority, maxSpu, isPreemptible); attr.GetAddr(), priority, maxSpu, isPreemptible);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
for (int i=0; i<9; i++) for (int i=0; i<8; i++)
if(priority[i] != 1 || maxSpu == 0) return CELL_SPURS_CORE_ERROR_INVAL; if(priority[i] != 1 || maxSpu == 0) return CELL_SPURS_CORE_ERROR_INVAL;
return CELL_OK; return CELL_OK;
@ -65,7 +65,7 @@ int cellSpursAttributeEnableSystemWorkload(mem_ptr_t<CellSpursAttribute> attr, c
int cellSpursInitializeWithAttribute2(mem_ptr_t<CellSpurs2> spurs, const mem_ptr_t<CellSpursAttribute> attr) int cellSpursInitializeWithAttribute2(mem_ptr_t<CellSpurs2> spurs, const mem_ptr_t<CellSpursAttribute> attr)
{ {
cellSpurs.Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)", cellSpurs.Error("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)",
spurs.GetAddr(), attr.GetAddr()); spurs.GetAddr(), attr.GetAddr());
if(!attr.IsGood() || !spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!attr.IsGood() || !spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -74,7 +74,7 @@ int cellSpursInitializeWithAttribute2(mem_ptr_t<CellSpurs2> spurs, const mem_ptr
int cellSpursFinalize(mem_ptr_t<CellSpurs> spurs) int cellSpursFinalize(mem_ptr_t<CellSpurs> spurs)
{ {
cellSpurs.Warning("cellSpursFinalize(spurs_addr=0x%x)", spurs.GetAddr()); cellSpurs.Error("cellSpursFinalize(spurs_addr=0x%x)", spurs.GetAddr());
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK; return CELL_OK;
@ -82,7 +82,7 @@ int cellSpursFinalize(mem_ptr_t<CellSpurs> spurs)
int cellSpursGetSpuThreadGroupId(mem_ptr_t<CellSpurs> spurs, mem32_t group) int cellSpursGetSpuThreadGroupId(mem_ptr_t<CellSpurs> spurs, mem32_t group)
{ {
cellSpurs.Warning("cellSpursGetSpuThreadGroupId(spurs_addr=0x%x, group_addr=0x%x)", cellSpurs.Error("cellSpursGetSpuThreadGroupId(spurs_addr=0x%x, group_addr=0x%x)",
spurs.GetAddr(), group.GetAddr()); spurs.GetAddr(), group.GetAddr());
if(!spurs.IsGood() || group.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood() || group.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -91,7 +91,7 @@ int cellSpursGetSpuThreadGroupId(mem_ptr_t<CellSpurs> spurs, mem32_t group)
int cellSpursGetNumSpuThread(mem_ptr_t<CellSpurs> spurs, mem32_t nThreads) int cellSpursGetNumSpuThread(mem_ptr_t<CellSpurs> spurs, mem32_t nThreads)
{ {
cellSpurs.Warning("cellSpursGetNumSpuThread(spurs_addr=0x%x, nThreads_addr=0x%x)", cellSpurs.Error("cellSpursGetNumSpuThread(spurs_addr=0x%x, nThreads_addr=0x%x)",
spurs.GetAddr(), nThreads.GetAddr()); spurs.GetAddr(), nThreads.GetAddr());
if(!spurs.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -100,7 +100,7 @@ int cellSpursGetNumSpuThread(mem_ptr_t<CellSpurs> spurs, mem32_t nThreads)
int cellSpursGetSpuThreadId(mem_ptr_t<CellSpurs> spurs, mem32_t thread, mem32_t nThreads) int cellSpursGetSpuThreadId(mem_ptr_t<CellSpurs> spurs, mem32_t thread, mem32_t nThreads)
{ {
cellSpurs.Warning("cellSpursGetSpuThreadId(spurs_addr=0x%x, thread_addr=0x%x, nThreads_addr=0x%x)", cellSpurs.Error("cellSpursGetSpuThreadId(spurs_addr=0x%x, thread_addr=0x%x, nThreads_addr=0x%x)",
spurs.GetAddr(), thread.GetAddr(), nThreads.GetAddr()); spurs.GetAddr(), thread.GetAddr(), nThreads.GetAddr());
if(!spurs.IsGood() || !thread.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood() || !thread.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -109,7 +109,7 @@ int cellSpursGetSpuThreadId(mem_ptr_t<CellSpurs> spurs, mem32_t thread, mem32_t
int cellSpursSetMaxContention(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint maxContention) int cellSpursSetMaxContention(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint maxContention)
{ {
cellSpurs.Warning("cellSpursSetMaxContention(spurs_addr=0x%x, workloadId=%u, maxContention=%u)", cellSpurs.Error("cellSpursSetMaxContention(spurs_addr=0x%x, workloadId=%u, maxContention=%u)",
spurs.GetAddr(), workloadId, maxContention); spurs.GetAddr(), workloadId, maxContention);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -118,7 +118,7 @@ int cellSpursSetMaxContention(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint
int cellSpursSetPriorities(mem_ptr_t<CellSpurs> spurs, uint workloadId, const u8 priorities[CELL_SPURS_MAX_SPU]) int cellSpursSetPriorities(mem_ptr_t<CellSpurs> spurs, uint workloadId, const u8 priorities[CELL_SPURS_MAX_SPU])
{ {
cellSpurs.Warning("cellSpursSetPriorities(spurs_addr=0x%x, workloadId=%u, priorities[%u])", cellSpurs.Error("cellSpursSetPriorities(spurs_addr=0x%x, workloadId=%u, priorities[%u])",
spurs.GetAddr(), workloadId, priorities); spurs.GetAddr(), workloadId, priorities);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -127,7 +127,7 @@ int cellSpursSetPriorities(mem_ptr_t<CellSpurs> spurs, uint workloadId, const u8
int cellSpursSetPriority(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint spuId, uint priority) int cellSpursSetPriority(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint spuId, uint priority)
{ {
cellSpurs.Warning("cellSpursSetPriority(spurs_addr=0x%x, workloadId=%u, spuId=%u, priority=%u)", cellSpurs.Error("cellSpursSetPriority(spurs_addr=0x%x, workloadId=%u, spuId=%u, priority=%u)",
spurs.GetAddr(), workloadId, spuId, priority); spurs.GetAddr(), workloadId, spuId, priority);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -136,7 +136,7 @@ int cellSpursSetPriority(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint spuId
int cellSpursSetPreemptionVictimHints(mem_ptr_t<CellSpurs> spurs, const bool isPreemptible[8]) int cellSpursSetPreemptionVictimHints(mem_ptr_t<CellSpurs> spurs, const bool isPreemptible[8])
{ {
cellSpurs.Warning("cellSpursSetPreemptionVictimHints(spurs_addr=0x%x, isPreemptible[%u])", cellSpurs.Error("cellSpursSetPreemptionVictimHints(spurs_addr=0x%x, isPreemptible[%u])",
spurs.GetAddr(), isPreemptible); spurs.GetAddr(), isPreemptible);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -145,7 +145,7 @@ int cellSpursSetPreemptionVictimHints(mem_ptr_t<CellSpurs> spurs, const bool isP
int cellSpursAttachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u32 queue, mem8_t port, int isDynamic) int cellSpursAttachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u32 queue, mem8_t port, int isDynamic)
{ {
cellSpurs.Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=0x%x, port_addr=0x%x, isDynamic=%u)", cellSpurs.Error("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=0x%x, port_addr=0x%x, isDynamic=%u)",
spurs.GetAddr(), queue, port.GetAddr(), isDynamic); spurs.GetAddr(), queue, port.GetAddr(), isDynamic);
if(!spurs.IsGood() || !port.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood() || !port.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -154,7 +154,7 @@ int cellSpursAttachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u32 queue, mem8_t p
int cellSpursDetachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u8 port) int cellSpursDetachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u8 port)
{ {
cellSpurs.Warning("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.GetAddr(), port); cellSpurs.Error("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.GetAddr(), port);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK; return CELL_OK;
@ -162,7 +162,7 @@ int cellSpursDetachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u8 port)
int cellSpursEnableExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, bool flag) int cellSpursEnableExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, bool flag)
{ {
cellSpurs.Warning("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, flag=%u)", spurs.GetAddr(), flag); cellSpurs.Error("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, flag=%u)", spurs.GetAddr(), flag);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK; return CELL_OK;
@ -171,7 +171,7 @@ int cellSpursEnableExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, bool flag)
int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs,
mem_func_ptr_t<CellSpursGlobalExceptionEventHandler> eaHandler, mem_ptr_t<void> arg) mem_func_ptr_t<CellSpursGlobalExceptionEventHandler> eaHandler, mem_ptr_t<void> arg)
{ {
cellSpurs.Warning("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, eaHandler_addr=0x%x, arg_addr=0x%x,)", cellSpurs.Error("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, eaHandler_addr=0x%x, arg_addr=0x%x,)",
spurs.GetAddr(), eaHandler.GetAddr(), arg.GetAddr()); spurs.GetAddr(), eaHandler.GetAddr(), arg.GetAddr());
if(!spurs.IsGood() || eaHandler.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood() || eaHandler.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
@ -180,7 +180,7 @@ int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs,
int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs) int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs)
{ {
cellSpurs.Warning("cellSpursUnsetGlobalExceptionEventHandler(spurs_addr=0x%x)", spurs.GetAddr()); cellSpurs.Error("cellSpursUnsetGlobalExceptionEventHandler(spurs_addr=0x%x)", spurs.GetAddr());
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK; return CELL_OK;
@ -188,7 +188,7 @@ int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs)
int cellSpursGetInfo(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursInfo> info) int cellSpursGetInfo(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursInfo> info)
{ {
cellSpurs.Warning("cellSpursGetInfo(spurs_addr=0x%x, info_addr=0x%x)", spurs.GetAddr(), info.GetAddr()); cellSpurs.Error("cellSpursGetInfo(spurs_addr=0x%x, info_addr=0x%x)", spurs.GetAddr(), info.GetAddr());
if(!spurs.IsGood() || !info.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; if(!spurs.IsGood() || !info.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK; return CELL_OK;
@ -197,7 +197,7 @@ int cellSpursGetInfo(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursInfo> info)
// Task functions // Task functions
int cellSpursGetTasksetId(mem_ptr_t<CellSpursTaskset> taskset, mem32_t workloadId) int cellSpursGetTasksetId(mem_ptr_t<CellSpursTaskset> taskset, mem32_t workloadId)
{ {
cellSpurs.Warning("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.GetAddr(), workloadId.GetAddr()); cellSpurs.Error("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.GetAddr(), workloadId.GetAddr());
if(!taskset.IsGood() || !taskset.IsGood()) return CELL_SPURS_TASK_ERROR_NULL_POINTER; if(!taskset.IsGood() || !taskset.IsGood()) return CELL_SPURS_TASK_ERROR_NULL_POINTER;
return CELL_OK; return CELL_OK;

View file

@ -87,7 +87,8 @@ struct CellSpursTraceInfo
//u8 padding[]; //u8 padding[];
}; };
__declspec(align(8)) struct CellTraceHeader //__declspec(align(8))
struct CellTraceHeader
{ {
u8 tag; u8 tag;
u8 length; u8 length;
@ -135,17 +136,20 @@ struct CellSpursTracePacket
} data; } data;
}; };
__declspec(align(128)) struct CellSpurs //__declspec(align(128))
struct CellSpurs
{ {
u8 skip[CELL_SPURS_SIZE]; u8 skip[CELL_SPURS_SIZE];
}; };
__declspec(align(128)) struct CellSpurs2 //__declspec(align(128))
struct CellSpurs2
{ {
u8 skip[CELL_SPURS_SIZE2 - CELL_SPURS_SIZE]; u8 skip[CELL_SPURS_SIZE2 - CELL_SPURS_SIZE];
}; };
__declspec(align(8)) struct CellSpursAttribute //__declspec(align(8))
struct CellSpursAttribute
{ {
u8 skip[CELL_SPURS_ATTRIBUTE_SIZE]; u8 skip[CELL_SPURS_ATTRIBUTE_SIZE];
}; };
@ -184,7 +188,8 @@ enum
}; };
__declspec(align(128)) struct CellSpursTaskset //__declspec(align(128))
struct CellSpursTaskset
{ {
u8 skip[6400]; u8 skip[6400];
}; };
@ -217,7 +222,8 @@ struct CellSpursTasksetInfo
#define CELL_SPURS_TASKSET_SIZE CELL_SPURS_TASKSET_CLASS0_SIZE #define CELL_SPURS_TASKSET_SIZE CELL_SPURS_TASKSET_CLASS0_SIZE
*/ */
__declspec(align(128)) struct CellSpursTaskset2 //__declspec(align(128))
struct CellSpursTaskset2
{ {
be_t<u8> skip[10496]; be_t<u8> skip[10496];
}; };
@ -267,7 +273,8 @@ struct CellSpursTaskAttribute2
//be_t<u32> __reserved__[]; //be_t<u32> __reserved__[];
}; };
__declspec(align(128)) struct CellSpursTaskExitCode //__declspec(align(128))
struct CellSpursTaskExitCode
{ {
unsigned char skip[128]; unsigned char skip[128];
}; };

View file

@ -166,7 +166,7 @@ int cellSysmoduleLoadModule(u16 id)
return CELL_SYSMODULE_ERROR_UNKNOWN; return CELL_SYSMODULE_ERROR_UNKNOWN;
} }
if(m->IsLoaded()) if(m->IsLoaded() && id != 0x10) // CELL_SYSMODULE_GCM_SYS and CELL_SYSMODULE_GCM share the same ID
{ {
return CELL_SYSMODULE_ERROR_DUPLICATED; return CELL_SYSMODULE_ERROR_DUPLICATED;
} }

View file

@ -3,145 +3,7 @@
#include "Emu/SysCalls/SC_FUNC.h" #include "Emu/SysCalls/SC_FUNC.h"
#include "Emu/Audio/sysutil_audio.h" #include "Emu/Audio/sysutil_audio.h"
// Parameter IDs #include "cellSysutil.h"
enum
{
//Integers
CELL_SYSUTIL_SYSTEMPARAM_ID_LANG = 0x0111,
CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN = 0x0112,
CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT = 0x0114,
CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT = 0x0115,
CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE = 0x0116,
CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME = 0x0117,
CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL = 0x0121,
CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT = 0x0123,
CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT = 0x0141,
CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ = 0x0151,
CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE = 0x0152,
CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE = 0x0153,
CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD = 0x0154,
CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD = 0x0155,
CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF = 0x0156,
//Strings
CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME = 0x113,
CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME = 0x131,
};
enum
{
CELL_SYSUTIL_LANG_JAPANESE = 0,
CELL_SYSUTIL_LANG_ENGLISH_US = 1,
CELL_SYSUTIL_LANG_FRENCH = 2,
CELL_SYSUTIL_LANG_SPANISH = 3,
CELL_SYSUTIL_LANG_GERMAN = 4,
CELL_SYSUTIL_LANG_ITALIAN = 5,
CELL_SYSUTIL_LANG_DUTCH = 6,
CELL_SYSUTIL_LANG_PORTUGUESE_PT = 7,
CELL_SYSUTIL_LANG_RUSSIAN = 8,
CELL_SYSUTIL_LANG_KOREAN = 9,
CELL_SYSUTIL_LANG_CHINESE_T = 10,
CELL_SYSUTIL_LANG_CHINESE_S = 11,
CELL_SYSUTIL_LANG_FINNISH = 12,
CELL_SYSUTIL_LANG_SWEDISH = 13,
CELL_SYSUTIL_LANG_DANISH = 14,
CELL_SYSUTIL_LANG_NORWEGIAN = 15,
CELL_SYSUTIL_LANG_POLISH = 16,
CELL_SYSUTIL_LANG_PORTUGUESE_BR = 17,
CELL_SYSUTIL_LANG_ENGLISH_GB = 18,
};
enum
{
CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE = 0,
CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CROSS = 1,
};
enum
{
CELL_SYSUTIL_DATE_FMT_YYYYMMDD = 0,
CELL_SYSUTIL_DATE_FMT_DDMMYYYY = 1,
CELL_SYSUTIL_DATE_FMT_MMDDYYYY = 2,
};
enum
{
CELL_SYSUTIL_TIME_FMT_CLOCK12 = 0,
CELL_SYSUTIL_TIME_FMT_CLOCK24 = 1,
};
enum
{
CELL_SYSUTIL_GAME_PARENTAL_OFF = 0,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL01 = 1,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL02 = 2,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL03 = 3,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL04 = 4,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL05 = 5,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL06 = 6,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL07 = 7,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL08 = 8,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL09 = 9,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL10 = 10,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL11 = 11,
};
enum
{
CELL_SYSUTIL_GAME_PARENTAL_LEVEL0_RESTRICT_OFF = 0,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL0_RESTRICT_ON = 1,
};
enum
{
CELL_SYSUTIL_CAMERA_PLFREQ_DISABLED = 0,
CELL_SYSUTIL_CAMERA_PLFREQ_50HZ = 1,
CELL_SYSUTIL_CAMERA_PLFREQ_60HZ = 2,
CELL_SYSUTIL_CAMERA_PLFREQ_DEVCIE_DEPEND = 4,
};
enum
{
CELL_SYSUTIL_PAD_RUMBLE_OFF = 0,
CELL_SYSUTIL_PAD_RUMBLE_ON = 1,
};
enum
{
CELL_MSGDIALOG_BUTTON_NONE = -1,
CELL_MSGDIALOG_BUTTON_INVALID = 0,
CELL_MSGDIALOG_BUTTON_OK = 1,
CELL_MSGDIALOG_BUTTON_YES = 1,
CELL_MSGDIALOG_BUTTON_NO = 2,
CELL_MSGDIALOG_BUTTON_ESCAPE = 3,
};
enum{
CELL_SYSCACHE_RET_OK_CLEARED = 0,
CELL_SYSCACHE_RET_OK_RELAYED = 1,
CELL_SYSCACHE_ID_SIZE = 32,
CELL_SYSCACHE_PATH_MAX = 1055,
CELL_SYSCACHE_ERROR_ACCESS_ERROR = 0x8002bc01,//I don't think we need this
CELL_SYSCACHE_ERROR_INTERNAL = 0x8002bc02,//not really useful, if we run out of HD space sysfs should handle that
CELL_SYSCACHE_ERROR_PARAM = 0x8002bc03,
CELL_SYSCACHE_ERROR_NOTMOUNTED = 0x8002bc04,//we don't really need to simulate the mounting, so this is probably useless
};
enum CellMsgDialogType
{
CELL_MSGDIALOG_DIALOG_TYPE_ERROR = 0x00000000,
CELL_MSGDIALOG_DIALOG_TYPE_NORMAL = 0x00000001,
CELL_MSGDIALOG_BUTTON_TYPE_NONE = 0x00000000,
CELL_MSGDIALOG_BUTTON_TYPE_YESNO = 0x00000010,
CELL_MSGDIALOG_DEFAULT_CURSOR_YES = 0x00000000,
CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100,
};
typedef void (*CellMsgDialogCallback)(int buttonType, mem_ptr_t<void> userData); typedef void (*CellMsgDialogCallback)(int buttonType, mem_ptr_t<void> userData);
@ -161,7 +23,7 @@ int cellSysutilGetSystemParamInt(int id, mem32_t value)
{ {
case CELL_SYSUTIL_SYSTEMPARAM_ID_LANG: case CELL_SYSUTIL_SYSTEMPARAM_ID_LANG:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_LANG"); cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_LANG");
value = CELL_SYSUTIL_LANG_ENGLISH_US; value = Ini.SysLanguage.GetValue();
break; break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN: case CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN:

View file

@ -0,0 +1,142 @@
#pragma once
// Parameter IDs
enum
{
// Integers
CELL_SYSUTIL_SYSTEMPARAM_ID_LANG = 0x0111,
CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN = 0x0112,
CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT = 0x0114,
CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT = 0x0115,
CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE = 0x0116,
CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME = 0x0117,
CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL = 0x0121,
CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT = 0x0123,
CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT = 0x0141,
CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ = 0x0151,
CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE = 0x0152,
CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE = 0x0153,
CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD = 0x0154,
CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD = 0x0155,
CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF = 0x0156,
// Strings
CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME = 0x113,
CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME = 0x131,
};
enum
{
CELL_SYSUTIL_LANG_JAPANESE = 0,
CELL_SYSUTIL_LANG_ENGLISH_US = 1,
CELL_SYSUTIL_LANG_FRENCH = 2,
CELL_SYSUTIL_LANG_SPANISH = 3,
CELL_SYSUTIL_LANG_GERMAN = 4,
CELL_SYSUTIL_LANG_ITALIAN = 5,
CELL_SYSUTIL_LANG_DUTCH = 6,
CELL_SYSUTIL_LANG_PORTUGUESE_PT = 7,
CELL_SYSUTIL_LANG_RUSSIAN = 8,
CELL_SYSUTIL_LANG_KOREAN = 9,
CELL_SYSUTIL_LANG_CHINESE_T = 10,
CELL_SYSUTIL_LANG_CHINESE_S = 11,
CELL_SYSUTIL_LANG_FINNISH = 12,
CELL_SYSUTIL_LANG_SWEDISH = 13,
CELL_SYSUTIL_LANG_DANISH = 14,
CELL_SYSUTIL_LANG_NORWEGIAN = 15,
CELL_SYSUTIL_LANG_POLISH = 16,
CELL_SYSUTIL_LANG_PORTUGUESE_BR = 17,
CELL_SYSUTIL_LANG_ENGLISH_GB = 18,
};
enum
{
CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE = 0,
CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CROSS = 1,
};
enum
{
CELL_SYSUTIL_DATE_FMT_YYYYMMDD = 0,
CELL_SYSUTIL_DATE_FMT_DDMMYYYY = 1,
CELL_SYSUTIL_DATE_FMT_MMDDYYYY = 2,
};
enum
{
CELL_SYSUTIL_TIME_FMT_CLOCK12 = 0,
CELL_SYSUTIL_TIME_FMT_CLOCK24 = 1,
};
enum
{
CELL_SYSUTIL_GAME_PARENTAL_OFF = 0,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL01 = 1,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL02 = 2,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL03 = 3,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL04 = 4,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL05 = 5,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL06 = 6,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL07 = 7,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL08 = 8,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL09 = 9,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL10 = 10,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL11 = 11,
};
enum
{
CELL_SYSUTIL_GAME_PARENTAL_LEVEL0_RESTRICT_OFF = 0,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL0_RESTRICT_ON = 1,
};
enum
{
CELL_SYSUTIL_CAMERA_PLFREQ_DISABLED = 0,
CELL_SYSUTIL_CAMERA_PLFREQ_50HZ = 1,
CELL_SYSUTIL_CAMERA_PLFREQ_60HZ = 2,
CELL_SYSUTIL_CAMERA_PLFREQ_DEVCIE_DEPEND = 4,
};
enum
{
CELL_SYSUTIL_PAD_RUMBLE_OFF = 0,
CELL_SYSUTIL_PAD_RUMBLE_ON = 1,
};
enum
{
CELL_MSGDIALOG_BUTTON_NONE = -1,
CELL_MSGDIALOG_BUTTON_INVALID = 0,
CELL_MSGDIALOG_BUTTON_OK = 1,
CELL_MSGDIALOG_BUTTON_YES = 1,
CELL_MSGDIALOG_BUTTON_NO = 2,
CELL_MSGDIALOG_BUTTON_ESCAPE = 3,
};
enum
{
CELL_SYSCACHE_RET_OK_CLEARED = 0,
CELL_SYSCACHE_RET_OK_RELAYED = 1,
CELL_SYSCACHE_ID_SIZE = 32,
CELL_SYSCACHE_PATH_MAX = 1055,
CELL_SYSCACHE_ERROR_ACCESS_ERROR = 0x8002bc01, // I don't think we need this
CELL_SYSCACHE_ERROR_INTERNAL = 0x8002bc02, // Not really useful, if we run out of HDD space sys_fs should handle that
CELL_SYSCACHE_ERROR_PARAM = 0x8002bc03,
CELL_SYSCACHE_ERROR_NOTMOUNTED = 0x8002bc04, // We don't really need to simulate the mounting, so this is probably useless
};
enum CellMsgDialogType
{
CELL_MSGDIALOG_DIALOG_TYPE_ERROR = 0x00000000,
CELL_MSGDIALOG_DIALOG_TYPE_NORMAL = 0x00000001,
CELL_MSGDIALOG_BUTTON_TYPE_NONE = 0x00000000,
CELL_MSGDIALOG_BUTTON_TYPE_YESNO = 0x00000010,
CELL_MSGDIALOG_DEFAULT_CURSOR_YES = 0x00000000,
CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100,
};

View file

@ -0,0 +1,75 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
#include "cellUserInfo.h"
void cellUserInfo_init();
Module cellUserInfo(0x0032, cellUserInfo_init);
int cellUserInfoGetStat(u32 id, mem_ptr_t<CellUserInfoUserStat> stat)
{
cellUserInfo.Warning("cellUserInfoGetStat(id=%d, stat_addr=0x%x)", id, stat.GetAddr());
if (!stat.IsGood())
return CELL_USERINFO_ERROR_PARAM;
if (id > CELL_USERINFO_USER_MAX)
return CELL_USERINFO_ERROR_NOUSER;
char path [256];
sprintf(path, "/dev_hdd0/home/%08d", id);
if (!Emu.GetVFS().ExistsDir(path))
return CELL_USERINFO_ERROR_NOUSER;
sprintf(path, "/dev_hdd0/home/%08d/localusername", id);
vfsStream* stream = Emu.GetVFS().OpenFile(path, vfsRead);
if (!stream || !(stream->IsOpened()))
return CELL_USERINFO_ERROR_INTERNAL;
char name [CELL_USERINFO_USERNAME_SIZE];
memset(name, 0, CELL_USERINFO_USERNAME_SIZE);
stream->Read(name, CELL_USERINFO_USERNAME_SIZE);
stream->Close();
stat->id = id;
memcpy(stat->name, name, CELL_USERINFO_USERNAME_SIZE);
return CELL_OK;
}
int cellUserInfoSelectUser_ListType()
{
UNIMPLEMENTED_FUNC(cellUserInfo);
return CELL_OK;
}
int cellUserInfoSelectUser_SetList()
{
UNIMPLEMENTED_FUNC(cellUserInfo);
return CELL_OK;
}
int cellUserInfoEnableOverlay()
{
UNIMPLEMENTED_FUNC(cellUserInfo);
return CELL_OK;
}
int cellUserInfoGetList(mem32_t listNum, mem_ptr_t<CellUserInfoUserList> listBuf, mem32_t currentUserId)
{
cellUserInfo.Warning("cellUserInfoGetList(listNum_addr=0x%x, listBuf_addr=0x%x, currentUserId_addr=0x%x)",
listNum.GetAddr(), listBuf.GetAddr(), currentUserId.GetAddr());
listNum = 1;
listBuf->userId[0] = 1;
currentUserId = 1;
return CELL_OK;
}
void cellUserInfo_init()
{
cellUserInfo.AddFunc(0x2b761140, cellUserInfoGetStat);
cellUserInfo.AddFunc(0x3097cc1c, cellUserInfoSelectUser_ListType);
cellUserInfo.AddFunc(0x55123a25, cellUserInfoSelectUser_SetList);
cellUserInfo.AddFunc(0xb3516536, cellUserInfoEnableOverlay);
cellUserInfo.AddFunc(0xc55e338b, cellUserInfoGetList);
}

View file

@ -0,0 +1,55 @@
#pragma once
// Return Codes
enum
{
CELL_USERINFO_RET_OK = 0,
CELL_USERINFO_RET_CANCEL = 1,
CELL_USERINFO_ERROR_BUSY = 0x8002c301,
CELL_USERINFO_ERROR_INTERNAL = 0x8002c302,
CELL_USERINFO_ERROR_PARAM = 0x8002c303,
CELL_USERINFO_ERROR_NOUSER = 0x8002c304,
};
// Enums
enum CellUserInfoParamSize
{
CELL_USERINFO_USER_MAX = 16,
CELL_USERINFO_TITLE_SIZE = 256,
CELL_USERINFO_USERNAME_SIZE = 64,
};
enum CellUserInfoListType
{
CELL_USERINFO_LISTTYPE_ALL = 0,
CELL_USERINFO_LISTTYPE_NOCURRENT = 1,
};
// Structs
struct CellUserInfoUserStat
{
u32 id;
u8 name[CELL_USERINFO_USERNAME_SIZE];
};
struct CellUserInfoUserList
{
u32 userId[CELL_USERINFO_USER_MAX];
};
struct CellUserInfoListSet
{
u32 title_addr; // (char*)
u32 focus;
u32 fixedListNum;
mem_ptr_t<CellUserInfoUserList> fixedList;
u32 reserved_addr; // (void*)
};
struct CellUserInfoTypeSet
{
u32 title_addr; // (char*)
u32 focus;
CellUserInfoListType type;
u32 reserved_addr; // (void*)
};

View file

@ -23,7 +23,8 @@ int vdecRead(void* opaque, u8* buf, int buf_size)
int res = 0; int res = 0;
if (vdec.reader.size < (u32)buf_size && !vdec.just_started) next:
if (vdec.reader.size < (u32)buf_size /*&& !vdec.just_started*/)
{ {
while (vdec.job.IsEmpty()) while (vdec.job.IsEmpty())
{ {
@ -74,6 +75,8 @@ int vdecRead(void* opaque, u8* buf, int buf_size)
ConLog.Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type); ConLog.Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type);
return 0; return 0;
} }
goto next;
} }
else if (vdec.reader.size < (u32)buf_size) else if (vdec.reader.size < (u32)buf_size)
{ {
@ -235,14 +238,21 @@ u32 vdecOpen(VideoDecoder* data)
if (vdec.just_started) // deferred initialization if (vdec.just_started) // deferred initialization
{ {
err = avformat_open_input(&vdec.fmt, NULL, NULL, NULL); err = avformat_open_input(&vdec.fmt, NULL, av_find_input_format("mpeg"), NULL);
if (err) if (err)
{ {
ConLog.Error("vdecDecodeAu: avformat_open_input() failed"); ConLog.Error("vdecDecodeAu: avformat_open_input() failed");
Emu.Pause(); Emu.Pause();
break; break;
} }
err = avformat_find_stream_info(vdec.fmt, NULL); AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); // ???
if (!codec)
{
ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed");
Emu.Pause();
break;
}
/*err = avformat_find_stream_info(vdec.fmt, NULL);
if (err) if (err)
{ {
ConLog.Error("vdecDecodeAu: avformat_find_stream_info() failed"); ConLog.Error("vdecDecodeAu: avformat_find_stream_info() failed");
@ -254,16 +264,14 @@ u32 vdecOpen(VideoDecoder* data)
ConLog.Error("vdecDecodeAu: no stream found"); ConLog.Error("vdecDecodeAu: no stream found");
Emu.Pause(); Emu.Pause();
break; break;
} }*/
vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data if (!avformat_new_stream(vdec.fmt, codec))
AVCodec* codec = avcodec_find_decoder(vdec.ctx->codec_id); // ???
if (!codec)
{ {
ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed"); ConLog.Error("vdecDecodeAu: avformat_new_stream() failed");
Emu.Pause(); Emu.Pause();
break; break;
} }
vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data
AVDictionary* opts = nullptr; AVDictionary* opts = nullptr;
av_dict_set(&opts, "refcounted_frames", "1", 0); av_dict_set(&opts, "refcounted_frames", "1", 0);
@ -292,6 +300,7 @@ u32 vdecOpen(VideoDecoder* data)
ConLog.Warning("vdecDecodeAu aborted"); ConLog.Warning("vdecDecodeAu aborted");
return; return;
} }
last_frame = av_read_frame(vdec.fmt, &au) < 0; last_frame = av_read_frame(vdec.fmt, &au) < 0;
if (last_frame) if (last_frame)
{ {
@ -335,7 +344,6 @@ u32 vdecOpen(VideoDecoder* data)
if (!last_frame && decode < 0) if (!last_frame && decode < 0)
{ {
ConLog.Error("vdecDecodeAu: AU decoding error(0x%x)", decode); ConLog.Error("vdecDecodeAu: AU decoding error(0x%x)", decode);
break;
} }
if (!got_picture && vdec.reader.size == 0) break; // video end? if (!got_picture && vdec.reader.size == 0) break; // video end?
} }

View file

@ -7,6 +7,37 @@
void sceNp_init(); void sceNp_init();
Module sceNp(0x0016, sceNp_init); Module sceNp(0x0016, sceNp_init);
int sceNpInit(u32 mem_size, u32 mem_addr)
{
sceNp.Log("sceNpInit(mem_size=0x%x, mem_addr=0x%x)", mem_size, mem_addr);
return CELL_OK;
}
int sceNpTerm()
{
sceNp.Log("sceNpTerm");
return CELL_OK;
}
int sceNpDrmIsAvailable(u32 k_licensee_addr, u32 drm_path_addr)
{
sceNp.Warning("sceNpDrmIsAvailable(k_licensee_addr=0x%x, drm_path_addr=0x%x)", k_licensee_addr, drm_path_addr);
wxString k_licensee_str;
wxString drm_path = Memory.ReadString(drm_path_addr);
u8 k_licensee[0x10];
for(int i = 0; i < 0x10; i++)
{
k_licensee[i] = Memory.Read8(k_licensee_addr + i);
k_licensee_str += wxString::Format("%02x", k_licensee[i]);
}
sceNp.Warning("sceNpDrmIsAvailable: Found DRM license file at %s", drm_path.wx_str());
sceNp.Warning("sceNpDrmIsAvailable: Using k_licensee 0x%s", k_licensee_str.wx_str());
return CELL_OK;
}
int sceNpManagerGetStatus(mem32_t status) int sceNpManagerGetStatus(mem32_t status)
{ {
sceNp.Log("sceNpManagerGetStatus(status_addr=0x%x)", status.GetAddr()); sceNp.Log("sceNpManagerGetStatus(status_addr=0x%x)", status.GetAddr());
@ -22,5 +53,8 @@ int sceNpManagerGetStatus(mem32_t status)
void sceNp_init() void sceNp_init()
{ {
sceNp.AddFunc(0xbd28fdbf, sceNpInit);
sceNp.AddFunc(0x4885aa18, sceNpTerm);
sceNp.AddFunc(0xad218faf, sceNpDrmIsAvailable);
sceNp.AddFunc(0xa7bff757, sceNpManagerGetStatus); sceNp.AddFunc(0xa7bff757, sceNpManagerGetStatus);
} }

View file

@ -4,6 +4,7 @@
#include "sceNp.h" #include "sceNp.h"
#include "sceNpTrophy.h" #include "sceNpTrophy.h"
#include "Loader/TRP.h" #include "Loader/TRP.h"
void sceNpTrophy_unload(); void sceNpTrophy_unload();
@ -110,29 +111,50 @@ int sceNpTrophyRegisterContext(u32 context, u32 handle, u32 statusCb_addr, u32 a
if (!Memory.IsGoodAddr(statusCb_addr)) if (!Memory.IsGoodAddr(statusCb_addr))
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT; return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT;
if (options & (~(u64)1)) if (options & (~(u64)1))
SCE_NP_TROPHY_ERROR_NOT_SUPPORTED; return SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
if (context >= s_npTrophyInstance.contexts.size()) if (context >= s_npTrophyInstance.contexts.size())
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT; return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
// TODO: There are other possible errors // TODO: There are other possible errors
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context]; sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
if (!ctxt.trp_stream) if (!ctxt.trp_stream)
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST; return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
int ret;
TRPLoader trp(*(ctxt.trp_stream)); TRPLoader trp(*(ctxt.trp_stream));
if (!trp.LoadHeader())
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
// Rename or discard certain entries based on the files found
char target [32];
sprintf(target, "TROP_%02d.SFM", Ini.SysLanguage.GetValue());
if (trp.ContainsEntry(target)) {
trp.RemoveEntry("TROPCONF.SFM");
trp.RemoveEntry("TROP.SFM");
trp.RenameEntry(target, "TROPCONF.SFM");
}
else if (trp.ContainsEntry("TROP.SFM")) {
trp.RemoveEntry("TROPCONF.SFM");
trp.RenameEntry("TROP.SFM", "TROPCONF.SFM");
}
else if (!trp.ContainsEntry("TROPCONF.SFM")) {
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
}
// Discard unnecessary TROP_XX.SFM files
for (int i=0; i<=18; i++) {
sprintf(target, "TROP_%02d.SFM", i);
if (i != Ini.SysLanguage.GetValue())
trp.RemoveEntry(target);
}
// TODO: Get the path of the current user // TODO: Get the path of the current user
if (trp.Install("/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name)) if (!trp.Install("/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name))
ret = CELL_OK; return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
else
ret = SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
// TODO: Callbacks // TODO: Callbacks
trp.Close(); return CELL_OK;
return ret;
} }
int sceNpTrophyGetGameProgress() int sceNpTrophyGetGameProgress()
@ -181,9 +203,32 @@ int sceNpTrophyAbortHandle()
return CELL_OK; return CELL_OK;
} }
int sceNpTrophyGetGameInfo() int sceNpTrophyGetGameInfo(u32 context, u32 handle, mem_ptr_t<SceNpTrophyGameDetails> details, mem_ptr_t<SceNpTrophyGameData> data)
{ {
UNIMPLEMENTED_FUNC(sceNpTrophy); sceNpTrophy.Warning("sceNpTrophyGetGameInfo(context=%d, handle=%d, details_addr=0x%x, data_addr=0x%x)",
context, handle, details.GetAddr(), data.GetAddr());
if (!s_npTrophyInstance.m_bInitialized)
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
if (!details.IsGood() || !data.IsGood())
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT;
// TODO: There are other possible errors
// sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
// TODO: This data is faked, implement a XML reader and get it from TROP.SFM
memcpy(details->title, "Trophy Set", SCE_NP_TROPHY_NAME_MAX_SIZE);
memcpy(details->description, "Hey! Implement a XML reader, and load the description from TROP.SFM", SCE_NP_TROPHY_DESCR_MAX_SIZE);
details->numTrophies = 0;
details->numPlatinum = 0;
details->numGold = 0;
details->numSilver = 0;
details->numBronze = 0;
data->unlockedTrophies = 0;
data->unlockedPlatinum = 0;
data->unlockedGold = 0;
data->unlockedSilver = 0;
data->unlockedBronze = 0;
return CELL_OK; return CELL_OK;
} }
@ -229,6 +274,8 @@ int sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, mem_ptr_t<Sc
// TODO: There are other possible errors // TODO: There are other possible errors
// sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context]; // sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
// TODO: This data is faked, implement a XML reader and get it from TROP.SFM
memcpy(details->name, "Some Trophy", SCE_NP_TROPHY_NAME_MAX_SIZE); memcpy(details->name, "Some Trophy", SCE_NP_TROPHY_NAME_MAX_SIZE);
memcpy(details->description, "Hey! Implement a XML reader, and load the description from TROP.SFM", SCE_NP_TROPHY_DESCR_MAX_SIZE); memcpy(details->description, "Hey! Implement a XML reader, and load the description from TROP.SFM", SCE_NP_TROPHY_DESCR_MAX_SIZE);
details->hidden = false; details->hidden = false;

View file

@ -57,7 +57,7 @@ enum
SCE_NP_TROPHY_DESCR_MAX_SIZE = 1024, SCE_NP_TROPHY_DESCR_MAX_SIZE = 1024,
}; };
enum enum SceNpTrophyGrade
{ {
SCE_NP_TROPHY_GRADE_UNKNOWN = 0, SCE_NP_TROPHY_GRADE_UNKNOWN = 0,
SCE_NP_TROPHY_GRADE_PLATINUM = 1, SCE_NP_TROPHY_GRADE_PLATINUM = 1,
@ -66,6 +66,27 @@ enum
SCE_NP_TROPHY_GRADE_BRONZE = 4, SCE_NP_TROPHY_GRADE_BRONZE = 4,
}; };
struct SceNpTrophyGameDetails
{
u32 numTrophies;
u32 numPlatinum;
u32 numGold;
u32 numSilver;
u32 numBronze;
u8 title[SCE_NP_TROPHY_TITLE_MAX_SIZE];
u8 description[SCE_NP_TROPHY_GAME_DESCR_MAX_SIZE];
u8 reserved[4];
};
struct SceNpTrophyGameData
{
u32 unlockedTrophies;
u32 unlockedPlatinum;
u32 unlockedGold;
u32 unlockedSilver;
u32 unlockedBronze;
};
struct SceNpTrophyDetails struct SceNpTrophyDetails
{ {
s32 trophyId; // SceNpTrophyId s32 trophyId; // SceNpTrophyId

View file

@ -167,7 +167,9 @@ void sysPrxForUser_init()
sysPrxForUser.AddFunc(0x44265c08, _sys_heap_memalign); sysPrxForUser.AddFunc(0x44265c08, _sys_heap_memalign);
sysPrxForUser.AddFunc(0xb257540b, sys_mmapper_allocate_memory); sysPrxForUser.AddFunc(0xb257540b, sys_mmapper_allocate_memory);
sysPrxForUser.AddFunc(0x70258515, sys_mmapper_allocate_memory_from_container);
sysPrxForUser.AddFunc(0xdc578057, sys_mmapper_map_memory); sysPrxForUser.AddFunc(0xdc578057, sys_mmapper_map_memory);
sysPrxForUser.AddFunc(0x4643ba6e, sys_mmapper_unmap_memory);
sysPrxForUser.AddFunc(0x409ad939, sys_mmapper_free_memory); sysPrxForUser.AddFunc(0x409ad939, sys_mmapper_free_memory);
sysPrxForUser.AddFunc(0x1ed454ce, sys_spu_elf_get_information); sysPrxForUser.AddFunc(0x1ed454ce, sys_spu_elf_get_information);
@ -185,6 +187,11 @@ void sysPrxForUser_init()
sysPrxForUser.AddFunc(0x52aadadf, sys_lwcond_signal_to); sysPrxForUser.AddFunc(0x52aadadf, sys_lwcond_signal_to);
sysPrxForUser.AddFunc(0x2a6d9d51, sys_lwcond_wait); sysPrxForUser.AddFunc(0x2a6d9d51, sys_lwcond_wait);
sysPrxForUser.AddFunc(0x8c2bb498, sys_spinlock_initialize);
sysPrxForUser.AddFunc(0xa285139d, sys_spinlock_lock);
sysPrxForUser.AddFunc(0x722a0254, sys_spinlock_trylock);
sysPrxForUser.AddFunc(0x5267cb35, sys_spinlock_unlock);
sysPrxForUser.AddFunc(0x67f9fedb, sys_game_process_exitspawn2); sysPrxForUser.AddFunc(0x67f9fedb, sys_game_process_exitspawn2);
sysPrxForUser.AddFunc(0xfc52a7a9, sys_game_process_exitspawn); sysPrxForUser.AddFunc(0xfc52a7a9, sys_game_process_exitspawn);

View file

@ -270,6 +270,25 @@ int cellFsAioFinish(mem8_ptr_t mount_point)
return CELL_OK; return CELL_OK;
} }
int cellFsReadWithOffset(u32 fd, u64 offset, u32 buf_addr, u64 buffer_size, mem64_t nread)
{
sys_fs.Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf_addr=0x%x, buffer_size=%lld nread=0x%llx)",
fd, offset, buf_addr, buffer_size, nread.GetAddr());
int ret;
MemoryAllocator<be_t<u64>> oldPos, newPos;
ret = cellFsLseek(fd, 0, CELL_SEEK_CUR, oldPos.GetAddr()); // Save the current position
if (ret) return ret;
ret = cellFsLseek(fd, offset, CELL_SEEK_SET, newPos.GetAddr()); // Move to the specified offset
if (ret) return ret;
ret = cellFsRead(fd, buf_addr, buffer_size, nread.GetAddr()); // Read the file
if (ret) return ret;
ret = cellFsLseek(fd, Memory.Read64(oldPos.GetAddr()), CELL_SEEK_SET, newPos.GetAddr()); // Return to the old position
if (ret) return ret;
return CELL_OK;
}
void sys_fs_init() void sys_fs_init()
{ {
sys_fs.AddFunc(0x718bf5f8, cellFsOpen); sys_fs.AddFunc(0x718bf5f8, cellFsOpen);
@ -295,5 +314,20 @@ void sys_fs_init()
sys_fs.AddFunc(0x9f951810, cellFsAioFinish); sys_fs.AddFunc(0x9f951810, cellFsAioFinish);
sys_fs.AddFunc(0x1a108ab7, cellFsGetBlockSize); sys_fs.AddFunc(0x1a108ab7, cellFsGetBlockSize);
sys_fs.AddFunc(0xaa3b4bcd, cellFsGetFreeSize); sys_fs.AddFunc(0xaa3b4bcd, cellFsGetFreeSize);
sys_fs.AddFunc(0x0d5b4a14, cellFsReadWithOffset);
sys_fs.AddFunc(0x9b882495, cellFsGetDirectoryEntries);
sys_fs.AddFunc(0x2664c8ae, cellFsStReadInit);
sys_fs.AddFunc(0xd73938df, cellFsStReadFinish);
sys_fs.AddFunc(0xb3afee8b, cellFsStReadGetRingBuf);
sys_fs.AddFunc(0xcf34969c, cellFsStReadGetStatus);
sys_fs.AddFunc(0xbd273a88, cellFsStReadGetRegid);
sys_fs.AddFunc(0x8df28ff9, cellFsStReadStart);
sys_fs.AddFunc(0xf8e5d9a0, cellFsStReadStop);
sys_fs.AddFunc(0x27800c6b, cellFsStRead);
sys_fs.AddFunc(0x190912f6, cellFsStReadGetCurrentAddr);
sys_fs.AddFunc(0x81f33783, cellFsStReadPutCurrentAddr);
sys_fs.AddFunc(0x8f71c5b2, cellFsStReadWait);
sys_fs.AddFunc(0x866f6aec, cellFsStReadWaitCallback);
aio_init = false; aio_init = false;
} }

View file

@ -2,25 +2,119 @@
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h" #include "Emu/SysCalls/SC_FUNC.h"
#include "sys_net.h"
#ifdef _WIN32
#include <winsock.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif
void sys_net_init(); void sys_net_init();
Module sys_net((u16)0x0000, sys_net_init); Module sys_net((u16)0x0000, sys_net_init);
int accept() mem32_t g_lastError(NULL);
// Auxiliary Functions
int inet_pton4(const char *src, char *dst)
{ {
UNIMPLEMENTED_FUNC(sys_net); const char digits[] = "0123456789";
return CELL_OK; int saw_digit, octets, ch;
unsigned char tmp[4], *tp;
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr(digits, ch)) != NULL) {
unsigned int n = *tp * 10 + (pch - digits);
if (n > 255)
return (0);
*tp = n;
if (! saw_digit) {
if (++octets > 4)
return (0);
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
if (octets == 4)
return 0;
*++tp = 0;
saw_digit = 0;
} else
return (0);
}
if (octets < 4)
return 0;
memcpy(dst, tmp, 4);
return 1;
} }
int bind() int inet_pton(int af, const char *src, char *dst)
{ {
UNIMPLEMENTED_FUNC(sys_net); switch (af) {
return CELL_OK; case AF_INET:
return (inet_pton4(src, dst));
default:
errno = EAFNOSUPPORT;
return -1;
}
} }
int connect() s32 getLastError()
{ {
UNIMPLEMENTED_FUNC(sys_net); #ifdef _WIN32
return CELL_OK; s32 ret = WSAGetLastError();
if (ret > 10000 && ret < 11000)
return ret % 10000;
else
return -1;
#else
return errno;
#endif
}
// Functions
int sys_net_accept(s32 s, mem_ptr_t<sys_net_sockaddr> addr, mem32_t paddrlen)
{
sys_net.Warning("accept(s=%d, family_addr=0x%x, paddrlen=0x%x)", s, addr.GetAddr(), paddrlen.GetAddr());
sockaddr _addr;
memcpy(&_addr, Memory.VirtualToRealAddr(addr.GetAddr()), sizeof(sockaddr));
_addr.sa_family = addr->sa_family;
s32 *_paddrlen = (s32 *)Memory.VirtualToRealAddr(paddrlen.GetAddr());
int ret = accept(s, &_addr, _paddrlen);
g_lastError = getLastError();
return ret;
}
int sys_net_bind(s32 s, mem_ptr_t<sys_net_sockaddr> family, u32 addrlen)
{
sys_net.Warning("bind(s=%d, family_addr=0x%x, addrlen=%u)", s, family.GetAddr(), addrlen);
sockaddr _family;
memcpy(&_family, Memory.VirtualToRealAddr(family.GetAddr()), sizeof(sockaddr));
_family.sa_family = family->sa_family;
int ret = bind(s, &_family, addrlen);
g_lastError = getLastError();
return ret;
}
int sys_net_connect(s32 s, mem_ptr_t<sys_net_sockaddr> family, u32 addrlen)
{
sys_net.Warning("connect(s=%d, family_addr=0x%x, addrlen=%u)", s, family.GetAddr(), addrlen);
sockaddr _family;
memcpy(&_family, Memory.VirtualToRealAddr(family.GetAddr()), sizeof(sockaddr));
_family.sa_family = family->sa_family;
int ret = connect(s, &_family, addrlen);
g_lastError = getLastError();
return ret;
} }
int gethostbyaddr() int gethostbyaddr()
@ -101,10 +195,12 @@ int inet_ntop()
return CELL_OK; return CELL_OK;
} }
int inet_pton() int sys_net_inet_pton(s32 af, u32 src_addr, u32 dst_addr)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("inet_pton(af=%d, src_addr=0x%x, dst_addr=0x%x)", af, src_addr, dst_addr);
return CELL_OK; char *src = (char *)Memory.VirtualToRealAddr(src_addr);
char *dst = (char *)Memory.VirtualToRealAddr(dst_addr);
return inet_pton(af, src, dst);
} }
int listen() int listen()
@ -113,16 +209,28 @@ int listen()
return CELL_OK; return CELL_OK;
} }
int recv() int sys_net_recv(s32 s, u32 buf_addr, u32 len, s32 flags)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("recv(s=%d, buf_addr=0x%x, len=%d, flags=0x%x)", s, buf_addr, len, flags);
return CELL_OK; char *buf = (char *)Memory.VirtualToRealAddr(buf_addr);
int ret = recv(s, buf, len, flags);
g_lastError = getLastError();
return ret;
} }
int recvfrom() int sys_net_recvfrom(s32 s, u32 buf_addr, u32 len, s32 flags, mem_ptr_t<sys_net_sockaddr> addr, mem32_t paddrlen)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("recvfrom(s=%d, buf_addr=0x%x, len=%u, flags=0x%x, addr_addr=0x%x, paddrlen=0x%x)",
return CELL_OK; s, buf_addr, len, flags, addr.GetAddr(), paddrlen.GetAddr());
char *_buf_addr = (char *)Memory.VirtualToRealAddr(buf_addr);
sockaddr _addr;
memcpy(&_addr, Memory.VirtualToRealAddr(addr.GetAddr()), sizeof(sockaddr));
_addr.sa_family = addr->sa_family;
s32 *_paddrlen = (s32 *)Memory.VirtualToRealAddr(paddrlen.GetAddr());
int ret = recvfrom(s, _buf_addr, len, flags, &_addr, _paddrlen);
g_lastError = getLastError();
return ret;
} }
int recvmsg() int recvmsg()
@ -131,10 +239,13 @@ int recvmsg()
return CELL_OK; return CELL_OK;
} }
int send() int sys_net_send(s32 s, u32 buf_addr, u32 len, s32 flags)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("send(s=%d, buf_addr=0x%x, len=%d, flags=0x%x)", s, buf_addr, len, flags);
return CELL_OK; char *buf = (char *)Memory.VirtualToRealAddr(buf_addr);
int ret = send(s, buf, len, flags);
g_lastError = getLastError();
return ret;
} }
int sendmsg() int sendmsg()
@ -143,34 +254,55 @@ int sendmsg()
return CELL_OK; return CELL_OK;
} }
int sendto() int sys_net_sendto(s32 s, u32 buf_addr, u32 len, s32 flags, mem_ptr_t<sys_net_sockaddr> addr, u32 addrlen)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("sendto(s=%d, buf_addr=0x%x, len=%u, flags=0x%x, addr=0x%x, addrlen=%u)",
return CELL_OK; s, buf_addr, len, flags, addr.GetAddr(), addrlen);
char *_buf_addr = (char *)Memory.VirtualToRealAddr(buf_addr);
sockaddr _addr;
memcpy(&_addr, Memory.VirtualToRealAddr(addr.GetAddr()), sizeof(sockaddr));
_addr.sa_family = addr->sa_family;
int ret = sendto(s, _buf_addr, len, flags, &_addr, addrlen);
g_lastError = getLastError();
return ret;
} }
int setsockopt() int sys_net_setsockopt(s32 s, s32 level, s32 optname, u32 optval_addr, u32 optlen)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("socket(s=%d, level=%d, optname=%d, optval_addr=0x%x, optlen=%u)", s, level, optname, optval_addr, optlen);
return CELL_OK; char *_optval_addr = (char *)Memory.VirtualToRealAddr(optval_addr);
int ret = setsockopt(s, level, optname, _optval_addr, optlen);
g_lastError = getLastError();
return ret;
} }
int shutdown() int sys_net_shutdown(s32 s, s32 how)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("shutdown(s=%d, how=%d)", s, how);
return CELL_OK; int ret = shutdown(s, how);
g_lastError = getLastError();
return ret;
} }
int socket() int sys_net_socket(s32 family, s32 type, s32 protocol)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("socket(family=%d, type=%d, protocol=%d)", family, type, protocol);
return CELL_OK; int ret = socket(family, type, protocol);
g_lastError = getLastError();
return ret;
} }
int socketclose() int sys_net_socketclose(s32 s)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("socket(s=%d)", s);
return CELL_OK; #ifdef _WIN32
int ret = closesocket(s);
#else
int ret = close(s);
#endif
g_lastError = getLastError();
return ret;
} }
int socketpoll() int socketpoll()
@ -185,9 +317,15 @@ int socketselect()
return CELL_OK; return CELL_OK;
} }
int sys_net_initialize_network_ex() int sys_net_initialize_network_ex(mem_ptr_t<sys_net_initialize_parameter> param)
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("sys_net_initialize_network_ex(param_addr=0x%x)", param.GetAddr());
g_lastError.SetAddr(Memory.Alloc(4, 1));
#ifdef _WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1,1);
WSAStartup(wVersionRequested, &wsaData);
#endif
return CELL_OK; return CELL_OK;
} }
@ -245,10 +383,10 @@ int sys_net_show_nameserver()
return CELL_OK; return CELL_OK;
} }
int _sys_net_errno_loc() s32 _sys_net_errno_loc()
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("_sys_net_errno_loc()");
return CELL_OK; return g_lastError.GetAddr();
} }
int sys_net_set_resolver_configurations() int sys_net_set_resolver_configurations()
@ -313,7 +451,12 @@ int sys_net_show_ifconfig()
int sys_net_finalize_network() int sys_net_finalize_network()
{ {
UNIMPLEMENTED_FUNC(sys_net); sys_net.Warning("sys_net_initialize_network_ex()");
Memory.Free(g_lastError.GetAddr());
g_lastError.SetAddr(NULL);
#ifdef _WIN32
WSACleanup();
#endif
return CELL_OK; return CELL_OK;
} }
@ -337,40 +480,39 @@ int sys_net_free_thread_context()
void sys_net_init() void sys_net_init()
{ {
// (TODO: Fix function overloading problem due to winsock.h and find addresses for ntohl and ntohs) // The names of the following functions are modified to avoid overloading problems
sys_net.AddFunc(0xc94f6939, sys_net_accept);
//sys_net.AddFunc(0xc94f6939, accept); sys_net.AddFunc(0xb0a59804, sys_net_bind);
//sys_net.AddFunc(0xb0a59804, bind); sys_net.AddFunc(0x64f66d35, sys_net_connect);
//sys_net.AddFunc(0x64f66d35, connect); //sys_net.AddFunc(0xf7ac8941, sys_net_gethostbyaddr);
//sys_net.AddFunc(0xf7ac8941, gethostbyaddr); //sys_net.AddFunc(0x71f4c717, sys_net_gethostbyname);
//sys_net.AddFunc(0x71f4c717, gethostbyname); //sys_net.AddFunc(0xf9ec2db6, sys_net_getpeername);
//sys_net.AddFunc(0xf9ec2db6, getpeername); //sys_net.AddFunc(0x13efe7f5, sys_net_getsockname);
//sys_net.AddFunc(0x13efe7f5, getsockname); //sys_net.AddFunc(0x5a045bd1, sys_net_getsockopt);
//sys_net.AddFunc(0x5a045bd1, getsockopt); //sys_net.AddFunc(0xdabbc2c0, sys_net_inet_addr);
//sys_net.AddFunc(0xdabbc2c0, inet_addr); //sys_net.AddFunc(0xa9a079e0, sys_net_inet_aton);
sys_net.AddFunc(0xa9a079e0, inet_aton); //sys_net.AddFunc(0x566893ce, sys_net_inet_lnaof);
sys_net.AddFunc(0x566893ce, inet_lnaof); //sys_net.AddFunc(0xb4152c74, sys_net_inet_makeaddr);
sys_net.AddFunc(0xb4152c74, inet_makeaddr); //sys_net.AddFunc(0xe39a62a7, sys_net_inet_netof);
sys_net.AddFunc(0xe39a62a7, inet_netof); //sys_net.AddFunc(0x506ad863, sys_net_inet_network);
sys_net.AddFunc(0x506ad863, inet_network); //sys_net.AddFunc(0x858a930b, sys_net_inet_ntoa);
//sys_net.AddFunc(0x858a930b, inet_ntoa); //sys_net.AddFunc(0xc98a3146, sys_net_inet_ntop);
sys_net.AddFunc(0xc98a3146, inet_ntop); sys_net.AddFunc(0x8af3825e, sys_net_inet_pton);
sys_net.AddFunc(0x8af3825e, inet_pton); //sys_net.AddFunc(0x28e208bb, sys_net_listen);
//sys_net.AddFunc(0x28e208bb, listen); //sys_net.AddFunc(, sys_net_ntohl);
//sys_net.AddFunc(, ntohl); //sys_net.AddFunc(, sys_net_ntohs);
//sys_net.AddFunc(, ntohs); sys_net.AddFunc(0xfba04f37, sys_net_recv);
//sys_net.AddFunc(0xfba04f37, recv); sys_net.AddFunc(0x1f953b9f, sys_net_recvfrom);
//sys_net.AddFunc(0x1f953b9f, recvfrom); //sys_net.AddFunc(0xc9d09c34, sys_net_recvmsg);
sys_net.AddFunc(0xc9d09c34, recvmsg); sys_net.AddFunc(0xdc751b40, sys_net_send);
//sys_net.AddFunc(0xdc751b40, send); //sys_net.AddFunc(0xad09481b, sys_net_sendmsg);
sys_net.AddFunc(0xad09481b, sendmsg); sys_net.AddFunc(0x9647570b, sys_net_sendto);
//sys_net.AddFunc(0x9647570b, sendto); sys_net.AddFunc(0x88f03575, sys_net_setsockopt);
//sys_net.AddFunc(0x88f03575, setsockopt); sys_net.AddFunc(0xa50777c6, sys_net_shutdown);
//sys_net.AddFunc(0xa50777c6, shutdown); sys_net.AddFunc(0x9c056962, sys_net_socket);
//sys_net.AddFunc(0x9c056962, socket); sys_net.AddFunc(0x6db6e8cd, sys_net_socketclose);
sys_net.AddFunc(0x6db6e8cd, socketclose); //sys_net.AddFunc(0x051ee3ee, sys_net_socketpoll);
sys_net.AddFunc(0x051ee3ee, socketpoll); //sys_net.AddFunc(0x3f09e20a, sys_net_socketselect);
sys_net.AddFunc(0x3f09e20a, socketselect);
sys_net.AddFunc(0x139a9e9b, sys_net_initialize_network_ex); sys_net.AddFunc(0x139a9e9b, sys_net_initialize_network_ex);
sys_net.AddFunc(0x05bd4438, sys_net_get_udpp2p_test_param); sys_net.AddFunc(0x05bd4438, sys_net_get_udpp2p_test_param);

View file

@ -0,0 +1,16 @@
#pragma once
struct sys_net_initialize_parameter
{
u32 memory_addr;
int memory_size;
int flags;
};
// The names of the following structs are modified to avoid overloading problems
struct sys_net_sockaddr
{
u8 sa_len;
u8 sa_family; // sa_family_t
u8 sa_data[14];
};

View file

@ -148,13 +148,28 @@ static func_caller* sc_table[1024] =
bind_func(sys_vm_get_statistics), //312 (0x138) bind_func(sys_vm_get_statistics), //312 (0x138)
null_func, null_func, //314 null_func, null_func, //314
null_func, null_func, null_func, null_func, null_func, //319 null_func, null_func, null_func, null_func, null_func, //319
null_func, null_func, null_func, null_func, bind_func(sys_memory_container_create), //324 null_func, null_func, null_func, null_func, //323
bind_func(sys_memory_container_destroy), null_func, null_func, null_func, null_func, //329 bind_func(sys_memory_container_create), //324
bind_func(sys_mmapper_allocate_address), null_func, null_func, null_func, null_func, //334 bind_func(sys_memory_container_destroy), //325
null_func, null_func, null_func, null_func, null_func, //339 bind_func(sys_mmapper_allocate_fixed_address), //326
null_func, bind_func(sys_memory_container_create), bind_func(sys_memory_container_destroy), null_func, null_func, //344 bind_func(sys_mmapper_enable_page_fault_notification), //327
null_func, null_func, null_func, bind_func(sys_memory_allocate), bind_func(sys_memory_free), //349 null_func, null_func, //329
null_func, bind_func(sys_memory_get_page_attribute), bind_func(sys_memory_get_user_memory_size), null_func, null_func, //354 bind_func(sys_mmapper_allocate_address), //330
bind_func(sys_mmapper_free_address), //331
null_func, null_func, null_func, null_func, //335
bind_func(sys_mmapper_change_address_access_right), //336
bind_func(sys_mmapper_search_and_map), //337
null_func, null_func, null_func, //340
bind_func(sys_memory_container_create), //341
bind_func(sys_memory_container_destroy), //342
bind_func(sys_memory_container_get_size), //343
null_func, null_func, null_func, null_func, //347
bind_func(sys_memory_allocate), //348
bind_func(sys_memory_free), //349
bind_func(sys_memory_allocate_from_container), //350
bind_func(sys_memory_get_page_attribute), //351
bind_func(sys_memory_get_user_memory_size), //352
null_func, null_func, //354
null_func, null_func, null_func, null_func, null_func, //359 null_func, null_func, null_func, null_func, null_func, //359
null_func, null_func, null_func, null_func, null_func, //364 null_func, null_func, null_func, null_func, null_func, //364
null_func, null_func, null_func, null_func, null_func, //369 null_func, null_func, null_func, null_func, null_func, //369

View file

@ -9,6 +9,7 @@
#include "lv2/SC_Lwcond.h" #include "lv2/SC_Lwcond.h"
#include "lv2/SC_Event_flag.h" #include "lv2/SC_Event_flag.h"
#include "lv2/SC_Condition.h" #include "lv2/SC_Condition.h"
#include "lv2/SC_Spinlock.h"
#include "Emu/event.h" #include "Emu/event.h"
//#define SYSCALLS_DEBUG //#define SYSCALLS_DEBUG
@ -200,6 +201,12 @@ extern int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout);
extern int sys_rwlock_trywlock(u32 rw_lock_id); extern int sys_rwlock_trywlock(u32 rw_lock_id);
extern int sys_rwlock_wunlock(u32 rw_lock_id); extern int sys_rwlock_wunlock(u32 rw_lock_id);
//sys_spinlock
extern void sys_spinlock_initialize(mem_ptr_t<spinlock> lock);
extern void sys_spinlock_lock(mem_ptr_t<spinlock> lock);
extern int sys_spinlock_trylock(mem_ptr_t<spinlock> lock);
extern void sys_spinlock_unlock(mem_ptr_t<spinlock> lock);
//ppu_thread //ppu_thread
extern void sys_ppu_thread_exit(u64 errorcode); extern void sys_ppu_thread_exit(u64 errorcode);
extern int sys_ppu_thread_yield(); extern int sys_ppu_thread_yield();
@ -216,16 +223,25 @@ extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry);
extern int sys_ppu_thread_get_id(const u32 id_addr); extern int sys_ppu_thread_get_id(const u32 id_addr);
//memory //memory
extern int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr);
extern int sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_addr_addr);
extern int sys_memory_free(u32 start_addr);
extern int sys_memory_get_page_attribute(u32 addr, mem_ptr_t<sys_page_attr_t> attr);
extern int sys_memory_get_user_memory_size(u32 mem_info_addr);
extern int sys_memory_container_create(mem32_t cid, u32 yield_size); extern int sys_memory_container_create(mem32_t cid, u32 yield_size);
extern int sys_memory_container_destroy(u32 cid); extern int sys_memory_container_destroy(u32 cid);
extern int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr); extern int sys_memory_container_get_size(u32 mem_info_addr, u32 cid);
extern int sys_memory_free(u32 start_addr);
extern int sys_memory_get_user_memory_size(u32 mem_info_addr);
extern int sys_memory_get_page_attribute(u32 addr, mem_ptr_t<sys_page_attr_t> a);
extern int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr); extern int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr);
extern int sys_mmapper_allocate_fixed_address();
extern int sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id); extern int sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id);
extern int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags); extern int sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, mem32_t mem_id);
extern int sys_mmapper_change_address_access_right(u32 start_addr, u64 flags);
extern int sys_mmapper_free_address(u32 start_addr);
extern int sys_mmapper_free_memory(u32 mem_id); extern int sys_mmapper_free_memory(u32 mem_id);
extern int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags);
extern int sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_addr);
extern int sys_mmapper_unmap_memory(u32 start_addr, u32 mem_id_addr);
extern int sys_mmapper_enable_page_fault_notification(u32 start_addr, u32 q_id);
//vm //vm
extern int sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr); extern int sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr);
@ -262,6 +278,19 @@ extern int cellFsTruncate(u32 path_addr, u64 size);
extern int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size); extern int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size);
extern int cellFsGetBlockSize(u32 path_addr, mem64_t sector_size, mem64_t block_size); extern int cellFsGetBlockSize(u32 path_addr, mem64_t sector_size, mem64_t block_size);
extern int cellFsGetFreeSize(u32 path_addr, mem32_t block_size, mem64_t block_count); extern int cellFsGetFreeSize(u32 path_addr, mem32_t block_size, mem64_t block_count);
extern int cellFsGetDirectoryEntries(u32 fd, mem_ptr_t<CellFsDirectoryEntry> entries, u32 entries_size, mem32_t data_count);
extern int cellFsStReadInit(u32 fd, mem_ptr_t<CellFsRingBuffer> ringbuf);
extern int cellFsStReadFinish(u32 fd);
extern int cellFsStReadGetRingBuf(u32 fd, mem_ptr_t<CellFsRingBuffer> ringbuf);
extern int cellFsStReadGetStatus(u32 fd, mem64_t status);
extern int cellFsStReadGetRegid(u32 fd, mem64_t regid);
extern int cellFsStReadStart(u32 fd, u64 offset, u64 size);
extern int cellFsStReadStop(u32 fd);
extern int cellFsStRead(u32 fd, u32 buf_addr, u64 size, mem64_t rsize);
extern int cellFsStReadGetCurrentAddr(u32 fd, mem32_t addr_addr, mem64_t size);
extern int cellFsStReadPutCurrentAddr(u32 fd, u32 addr_addr, u64 size);
extern int cellFsStReadWait(u32 fd, u64 size);
extern int cellFsStReadWaitCallback(u32 fd, u64 size, mem_func_ptr_t<void (*)(int xfd, u64 xsize)> func);
//cellVideo //cellVideo
extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr); extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr);

View file

@ -71,48 +71,15 @@ int sys_cond_signal(u32 cond_id)
} }
Mutex* mutex = cond->mutex; Mutex* mutex = cond->mutex;
u32 tid = GetCurrentPPUThread().GetId();
bool was_locked = (mutex->m_mutex.GetOwner() == tid);
if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop())) if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
{ {
CPUThread* tt = Emu.GetCPU().GetThread(target); cond->cond.lock(target);
bool valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal(%d): signal to invalid thread(%d)", cond_id, target);
return CELL_OK;
}
if (!was_locked) // mutex hasn't been locked (don't care about mutex state) if (Emu.IsStopped())
{ {
if (u32 owner = mutex->m_mutex.GetOwner()) ConLog.Warning("sys_cond_signal(id=%d) aborted", cond_id);
{
tt = Emu.GetCPU().GetThread(owner);
valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal(%d): deadlock on invalid thread(%d)", cond_id, owner);
return CELL_OK;
}
}
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);
} }
else // mutex has been locked (should preserve original mutex state)
{
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
}
}
if (Emu.IsStopped())
{
ConLog.Warning("sys_cond_signal(id=%d) aborted", cond_id);
} }
return CELL_OK; return CELL_OK;
@ -129,43 +96,10 @@ int sys_cond_signal_all(u32 cond_id)
} }
Mutex* mutex = cond->mutex; Mutex* mutex = cond->mutex;
u32 tid = GetCurrentPPUThread().GetId();
bool was_locked = (mutex->m_mutex.GetOwner() == tid);
while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop())) while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
{ {
CPUThread* tt = Emu.GetCPU().GetThread(target); cond->cond.lock(target);
bool valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal_all(%d): signal to invalid thread(%d)", cond_id, target);
return CELL_OK;
}
if (!was_locked)
{
if (u32 owner = mutex->m_mutex.GetOwner())
{
tt = Emu.GetCPU().GetThread(owner);
valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal_all(%d): deadlock on invalid thread(%d)", cond_id, owner);
return CELL_OK;
}
}
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);
}
else
{
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
}
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
@ -197,35 +131,10 @@ int sys_cond_signal_to(u32 cond_id, u32 thread_id)
} }
Mutex* mutex = cond->mutex; Mutex* mutex = cond->mutex;
u32 tid = GetCurrentPPUThread().GetId();
bool was_locked = (mutex->m_mutex.GetOwner() == tid);
u32 target = thread_id; u32 target = thread_id;
{ {
if (!was_locked) cond->cond.lock(target);
{
if (u32 owner = mutex->m_mutex.GetOwner())
{
CPUThread* tt = Emu.GetCPU().GetThread(owner);
bool valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal_to(%d): deadlock on invalid thread(%d)", cond_id, owner);
return CELL_OK;
}
}
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);
}
else
{
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
}
} }
if (Emu.IsStopped()) if (Emu.IsStopped())
@ -264,15 +173,11 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
while (true) while (true)
{ {
/* switch (mutex->m_mutex.trylock(tid)) if (cond->cond.GetOwner() == tid)
{ {
case SMR_OK: mutex->m_mutex.unlock(tid); break; mutex->m_mutex.lock(tid);
case SMR_SIGNAL: mutex->recursive = 1; return CELL_OK;
} */
if (mutex->m_mutex.GetOwner() == tid)
{
_mm_mfence();
mutex->recursive = 1; mutex->recursive = 1;
cond->cond.unlock(tid);
return CELL_OK; return CELL_OK;
} }
@ -281,6 +186,7 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
if (counter++ > max_counter) if (counter++ > max_counter)
{ {
cond->m_queue.invalidate(tid); cond->m_queue.invalidate(tid);
GetCurrentPPUThread().owned_mutexes--;
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
if (Emu.IsStopped()) if (Emu.IsStopped())

View file

@ -16,6 +16,7 @@ struct sys_cond_attribute
struct Cond struct Cond
{ {
Mutex* mutex; // associated with mutex Mutex* mutex; // associated with mutex
SMutex cond;
SleepQueue m_queue; SleepQueue m_queue;
Cond(Mutex* mutex, u64 name) Cond(Mutex* mutex, u64 name)

View file

@ -203,7 +203,7 @@ int sys_event_queue_receive(u32 equeue_id, mem_ptr_t<sys_event_data> event, u64
eq->owner.unlock(tid); eq->owner.unlock(tid);
sys_event.Log(" *** event received: source=0x%llx, d1=0x%llx, d2=0x%llx, d3=0x%llx", sys_event.Log(" *** event received: source=0x%llx, d1=0x%llx, d2=0x%llx, d3=0x%llx",
(u64)event->source, (u64)event->data1, (u64)event->data2, (u64)event->data3); (u64)event->source, (u64)event->data1, (u64)event->data2, (u64)event->data3);
/* HACK: passing event data in registers */ /* passing event data in registers */
PPUThread& t = GetCurrentPPUThread(); PPUThread& t = GetCurrentPPUThread();
t.GPR[4] = event->source; t.GPR[4] = event->source;
t.GPR[5] = event->data1; t.GPR[5] = event->data1;

View file

@ -10,6 +10,39 @@ enum
IDFlag_Dir = 2, IDFlag_Dir = 2,
}; };
struct FsRingBuffer
{
u64 m_ringbuf_size;
u64 m_block_size;
u64 m_transfer_rate;
u32 m_copy;
};
struct FsRingBufferConfig
{
FsRingBuffer m_ring_buffer;
u32 m_buffer;
u64 m_fs_status;
u64 m_regid;
u32 m_alloc_mem_size;
u32 m_current_addr;
FsRingBufferConfig()
: m_fs_status(CELL_FS_ST_NOT_INITIALIZED)
, m_regid(0)
, m_alloc_mem_size(0)
, m_current_addr(0)
{
memset(&m_ring_buffer, 0, sizeof(FsRingBufferConfig));
}
~FsRingBufferConfig()
{
memset(&m_ring_buffer, 0, sizeof(FsRingBufferConfig));
}
} m_fs_config;
int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
{ {
const wxString& path = Memory.ReadString(path_addr); const wxString& path = Memory.ReadString(path_addr);
@ -291,10 +324,15 @@ int cellFsMkdir(u32 path_addr, u32 mode)
const wxString& ps3_path = Memory.ReadString(path_addr); const wxString& ps3_path = Memory.ReadString(path_addr);
sys_fs.Log("cellFsMkdir(path=\"%s\", mode=0x%x)", ps3_path.wx_str(), mode); sys_fs.Log("cellFsMkdir(path=\"%s\", mode=0x%x)", ps3_path.wx_str(), mode);
vfsDir dir; /*vfsDir dir;
if(dir.IsExists(ps3_path)) if(dir.IsExists(ps3_path))
return CELL_EEXIST; return CELL_EEXIST;
if(!dir.Create(ps3_path)) if(!dir.Create(ps3_path))
return CELL_EBUSY;*/
if(Emu.GetVFS().ExistsDir(ps3_path))
return CELL_EEXIST;
if(!Emu.GetVFS().CreateDir(ps3_path))
return CELL_EBUSY; return CELL_EBUSY;
return CELL_OK; return CELL_OK;
@ -484,3 +522,217 @@ int cellFsGetFreeSize(u32 path_addr, mem32_t block_size, mem64_t block_count)
return CELL_OK; return CELL_OK;
} }
int cellFsGetDirectoryEntries(u32 fd, mem_ptr_t<CellFsDirectoryEntry> entries, u32 entries_size, mem32_t data_count)
{
sys_fs.Log("cellFsGetDirectoryEntries(fd=%d, entries_addr=0x%x, entries_size = 0x%x, data_count_addr=0x%x)", fd, entries.GetAddr(), entries_size, data_count.GetAddr());
vfsDirBase* directory;
if(!sys_fs.CheckId(fd, directory))
return CELL_ESRCH;
if(!entries.IsGood() || !data_count.IsGood())
return CELL_EFAULT;
const DirEntryInfo* info = directory->Read();
if(info)
{
data_count = 1;
Memory.WriteString(entries.GetAddr()+2, info->name.wx_str());
entries->entry_name.d_namlen = info->name.Length();
entries->entry_name.d_type = (info->flags & DirEntry_TypeFile) ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY;
entries->attribute.st_mode =
CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR |
CELL_FS_S_IRGRP | CELL_FS_S_IWGRP | CELL_FS_S_IXGRP |
CELL_FS_S_IROTH | CELL_FS_S_IWOTH | CELL_FS_S_IXOTH;
entries->attribute.st_uid = 0;
entries->attribute.st_gid = 0;
entries->attribute.st_atime_ = 0; //TODO
entries->attribute.st_mtime_ = 0; //TODO
entries->attribute.st_ctime_ = 0; //TODO
entries->attribute.st_blksize = 4096;
}
else
{
data_count = 0;
}
return CELL_OK;
}
int cellFsStReadInit(u32 fd, mem_ptr_t<CellFsRingBuffer> ringbuf)
{
sys_fs.Warning("cellFsStReadInit(fd=%d, ringbuf_addr=0x%x)", fd, ringbuf.GetAddr());
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
if(!ringbuf.IsGood())
return CELL_EFAULT;
FsRingBuffer& buffer = m_fs_config.m_ring_buffer;
buffer.m_block_size = ringbuf->block_size;
buffer.m_copy = ringbuf->copy;
buffer.m_ringbuf_size = ringbuf->ringbuf_size;
buffer.m_transfer_rate = ringbuf->transfer_rate;
if(buffer.m_ringbuf_size < 0x40000000) // If the size is less than 1MB
m_fs_config.m_alloc_mem_size = ((ringbuf->ringbuf_size + 64 * 1024 - 1) / (64 * 1024)) * (64 * 1024);
m_fs_config.m_alloc_mem_size = ((ringbuf->ringbuf_size + 1024 * 1024 - 1) / (1024 * 1024)) * (1024 * 1024);
// alloc memory
m_fs_config.m_buffer = Memory.Alloc(m_fs_config.m_alloc_mem_size, 1024);
memset(Memory + m_fs_config.m_buffer, 0, m_fs_config.m_alloc_mem_size);
m_fs_config.m_fs_status = CELL_FS_ST_INITIALIZED;
return CELL_OK;
}
int cellFsStReadFinish(u32 fd)
{
sys_fs.Warning("cellFsStReadFinish(fd=%d)", fd);
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
Memory.Free(m_fs_config.m_buffer);
m_fs_config.m_fs_status = CELL_FS_ST_NOT_INITIALIZED;
return CELL_OK;
}
int cellFsStReadGetRingBuf(u32 fd, mem_ptr_t<CellFsRingBuffer> ringbuf)
{
sys_fs.Warning("cellFsStReadGetRingBuf(fd=%d, ringbuf_addr=0x%x)", fd, ringbuf.GetAddr());
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
if(!ringbuf.IsGood())
return CELL_EFAULT;
FsRingBuffer& buffer = m_fs_config.m_ring_buffer;
ringbuf->block_size = buffer.m_block_size;
ringbuf->copy = buffer.m_copy;
ringbuf->ringbuf_size = buffer.m_ringbuf_size;
ringbuf->transfer_rate = buffer.m_transfer_rate;
sys_fs.Warning("*** fs stream config: block_size=0x%llx, copy=%d, ringbuf_size = 0x%llx, transfer_rate = 0x%llx", ringbuf->block_size, ringbuf->copy,
ringbuf->ringbuf_size, ringbuf->transfer_rate);
return CELL_OK;
}
int cellFsStReadGetStatus(u32 fd, mem64_t status)
{
sys_fs.Warning("cellFsStReadGetRingBuf(fd=%d, status_addr=0x%x)", fd, status.GetAddr());
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
status = m_fs_config.m_fs_status;
return CELL_OK;
}
int cellFsStReadGetRegid(u32 fd, mem64_t regid)
{
sys_fs.Warning("cellFsStReadGetRingBuf(fd=%d, regid_addr=0x%x)", fd, regid.GetAddr());
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
regid = m_fs_config.m_regid;
return CELL_OK;
}
int cellFsStReadStart(u32 fd, u64 offset, u64 size)
{
sys_fs.Warning("TODO: cellFsStReadStart(fd=%d, offset=0x%llx, size=0x%llx)", fd, offset, size);
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
m_fs_config.m_current_addr = m_fs_config.m_buffer + (u32)offset;
m_fs_config.m_fs_status = CELL_FS_ST_PROGRESS;
return CELL_OK;
}
int cellFsStReadStop(u32 fd)
{
sys_fs.Warning("cellFsStReadStop(fd=%d)", fd);
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
m_fs_config.m_fs_status = CELL_FS_ST_STOP;
return CELL_OK;
}
int cellFsStRead(u32 fd, u32 buf_addr, u64 size, mem64_t rsize)
{
sys_fs.Warning("TODO: cellFsStRead(fd=%d, buf_addr=0x%x, size=0x%llx, rsize_addr = 0x%x)", fd, buf_addr, size, rsize.GetAddr());
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
if (rsize.GetAddr() && !rsize.IsGood()) return CELL_EFAULT;
m_fs_config.m_regid += size;
rsize = m_fs_config.m_regid;
return CELL_OK;
}
int cellFsStReadGetCurrentAddr(u32 fd, mem32_t addr_addr, mem64_t size)
{
sys_fs.Warning("TODO: cellFsStReadGetCurrentAddr(fd=%d, addr_addr=0x%x, size_addr = 0x%x)", fd, addr_addr.GetAddr(), size.GetAddr());
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
if (!addr_addr.IsGood() && !size.IsGood()) return CELL_EFAULT;
return CELL_OK;
}
int cellFsStReadPutCurrentAddr(u32 fd, u32 addr_addr, u64 size)
{
sys_fs.Warning("TODO: cellFsStReadPutCurrentAddr(fd=%d, addr_addr=0x%x, size = 0x%llx)", fd, addr_addr, size);
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
if (!Memory.IsGoodAddr(addr_addr)) return CELL_EFAULT;
return CELL_OK;
}
int cellFsStReadWait(u32 fd, u64 size)
{
sys_fs.Warning("TODO: cellFsStReadWait(fd=%d, size = 0x%llx)", fd, size);
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
return CELL_OK;
}
int cellFsStReadWaitCallback(u32 fd, u64 size, mem_func_ptr_t<void (*)(int xfd, u64 xsize)> func)
{
sys_fs.Warning("TODO: cellFsStReadWaitCallback(fd=%d, size = 0x%llx, func_addr = 0x%x)", fd, size, func.GetAddr());
if (!func.IsGood())
return CELL_EFAULT;
vfsStream* file;
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
return CELL_OK;
}

View file

@ -56,6 +56,21 @@ enum FsDirentType
CELL_FS_TYPE_SYMLINK = 3, CELL_FS_TYPE_SYMLINK = 3,
}; };
enum CellFsRingBufferCopy
{
CELL_FS_ST_COPY = 0,
CELL_FS_ST_COPYLESS = 1,
};
enum cellFsStStatus
{
CELL_FS_ST_INITIALIZED = 0x0001,
CELL_FS_ST_NOT_INITIALIZED = 0x0002,
CELL_FS_ST_STOP = 0x0100,
CELL_FS_ST_PROGRESS = 0x0200,
};
#pragma pack(4) #pragma pack(4)
struct CellFsStat struct CellFsStat
@ -93,3 +108,17 @@ struct CellFsAio
be_t<u64> size; be_t<u64> size;
be_t<u64> user_data; be_t<u64> user_data;
}; };
struct CellFsDirectoryEntry
{
CellFsStat attribute;
CellFsDirent entry_name;
};
struct CellFsRingBuffer
{
be_t<u64> ringbuf_size;
be_t<u64> block_size;
be_t<u64> transfer_rate;
be_t<u32> copy;
};

View file

@ -198,6 +198,7 @@ bool SleepQueue::finalize()
} }
} }
m_mutex.unlock();
return true; return true;
} }

View file

@ -1,52 +1,16 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
#include "SC_Memory.h" #include "SC_Memory.h"
#include <map>
SysCallBase sc_mem("memory"); SysCallBase sc_mem("memory");
std::map<u32, u32> mmapper_info_map;
int sys_memory_container_create(mem32_t cid, u32 yield_size)
{
sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x, yield_size=0x%x)", cid.GetAddr(), yield_size);
if (!cid.IsGood())
{
return CELL_EFAULT;
}
yield_size &= ~0xfffff; //round down to 1 MB granularity
u64 addr = Memory.Alloc(yield_size, 0x100000); //1 MB alignment
if(!addr)
{
return CELL_ENOMEM;
}
cid = sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size));
sc_mem.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, cid.GetValue());
return CELL_OK;
}
int sys_memory_container_destroy(u32 cid)
{
sc_mem.Warning("sys_memory_container_destroy(cid=%d)", cid);
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
{
return CELL_ESRCH;
}
Memory.Free(ct->addr);
Emu.GetIdManager().RemoveID(cid);
return CELL_OK;
}
int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr) int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
{ {
//0x30000100;
sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags); sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
// Check page size.
u32 addr; u32 addr;
switch(flags) switch(flags)
{ {
@ -63,119 +27,64 @@ int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
default: return CELL_EINVAL; default: return CELL_EINVAL;
} }
if(!addr) return CELL_ENOMEM; if(!addr)
return CELL_ENOMEM;
// Write back the start address of the allocated area.
sc_mem.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", addr, size); sc_mem.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", addr, size);
Memory.Write32(alloc_addr_addr, addr); Memory.Write32(alloc_addr_addr, addr);
return CELL_OK; return CELL_OK;
} }
int sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_addr_addr)
{
sc_mem.Log("sys_memory_allocate_from_container(size=0x%x, cid=0x%x, flags=0x%x)", size, cid, flags);
// Check if this container ID is valid.
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
return CELL_ESRCH;
// Check page size.
switch(flags)
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN;
ct->addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN;
ct->addr = Memory.Alloc(size, 0x10000);
break;
default: return CELL_EINVAL;
}
// Store the address and size in the container.
if(!ct->addr)
return CELL_ENOMEM;
ct->size = size;
// Write back the start address of the allocated area.
sc_mem.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", ct->addr, ct->size);
Memory.Write32(alloc_addr_addr, ct->addr);
return CELL_OK;
}
int sys_memory_free(u32 start_addr) int sys_memory_free(u32 start_addr)
{ {
sc_mem.Log("sys_memory_free(start_addr=0x%x)", start_addr); sc_mem.Log("sys_memory_free(start_addr=0x%x)", start_addr);
if(!Memory.Free(start_addr)) return CELL_EFAULT; // Release the allocated memory.
if(!Memory.Free(start_addr))
return CELL_EFAULT;
return CELL_OK; return CELL_OK;
} }
int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr)
{
sc_mem.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)", size, flags, alignment, alloc_addr);
if(!Memory.IsGoodAddr(alloc_addr)) return CELL_EFAULT;
if(!alignment)
alignment = 1;
u32 addr;
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
{
default:
case SYS_MEMORY_PAGE_SIZE_1M:
if(Memory.AlignAddr(size, alignment) & 0xfffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(Memory.AlignAddr(size, alignment) & 0xffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
break;
}
Memory.Write32(alloc_addr, addr);
return CELL_OK;
}
int sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id)
{
sc_mem.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id.GetAddr());
if(!mem_id.IsGood()) return CELL_EFAULT;
u32 addr;
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
break;
default:
return CELL_EINVAL;
}
if(!addr)
return CELL_ENOMEM;
mem_id = sc_mem.GetNewId(new mmapper_info(addr, size, flags));
return CELL_OK;
}
int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags)
{
sc_mem.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags);
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info)) return CELL_ESRCH;
if(!Memory.Map(start_addr, info->addr, info->size))
{
sc_mem.Error("sys_mmapper_map_memory failed!");
}
return CELL_OK;
}
int sys_mmapper_free_memory(u32 mem_id)
{
sc_mem.Warning("sys_mmapper_free_memory(mem_id=0x%x)", mem_id);
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info)) return CELL_ESRCH;
Memory.Free(info->addr);
return CELL_OK;
}
int sys_memory_get_user_memory_size(u32 mem_info_addr)
{
sc_mem.Warning("sys_memory_get_user_memory_size(mem_info_addr=0x%x)", mem_info_addr);
sys_memory_info info;
info.total_user_memory = re(Memory.GetUserMemTotalSize());
info.available_user_memory = re(Memory.GetUserMemAvailSize());
Memory.WriteData(mem_info_addr, info);
return CELL_OK;
}
int sys_memory_get_page_attribute(u32 addr, mem_ptr_t<sys_page_attr_t> attr) int sys_memory_get_page_attribute(u32 addr, mem_ptr_t<sys_page_attr_t> attr)
{ {
sc_mem.Warning("sys_memory_get_page_attribute(addr=0x%x, attr_addr=0x%x)", addr, attr.GetAddr()); sc_mem.Warning("sys_memory_get_page_attribute(addr=0x%x, attr_addr=0x%x)", addr, attr.GetAddr());
@ -183,6 +92,7 @@ int sys_memory_get_page_attribute(u32 addr, mem_ptr_t<sys_page_attr_t> attr)
if (!attr.IsGood()) if (!attr.IsGood())
return CELL_EFAULT; return CELL_EFAULT;
// TODO: Implement per thread page attribute setting.
attr->attribute = 0; attr->attribute = 0;
attr->page_size = 0; attr->page_size = 0;
attr->access_right = 0; attr->access_right = 0;
@ -190,3 +100,327 @@ int sys_memory_get_page_attribute(u32 addr, mem_ptr_t<sys_page_attr_t> attr)
return CELL_OK; return CELL_OK;
} }
int sys_memory_get_user_memory_size(u32 mem_info_addr)
{
sc_mem.Warning("sys_memory_get_user_memory_size(mem_info_addr=0x%x)", mem_info_addr);
// Fetch the user memory available.
sys_memory_info info;
info.total_user_memory = re(Memory.GetUserMemTotalSize());
info.available_user_memory = re(Memory.GetUserMemAvailSize());
Memory.WriteData(mem_info_addr, info);
return CELL_OK;
}
int sys_memory_container_create(mem32_t cid, u32 yield_size)
{
sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x, yield_size=0x%x)", cid.GetAddr(), yield_size);
if (!cid.IsGood())
return CELL_EFAULT;
yield_size &= ~0xfffff; //round down to 1 MB granularity
u64 addr = Memory.Alloc(yield_size, 0x100000); //1 MB alignment
if(!addr)
return CELL_ENOMEM;
// Wrap the allocated memory in a memory container.
MemoryContainerInfo *ct = new MemoryContainerInfo(addr, yield_size);
cid = sc_mem.GetNewId(ct);
sc_mem.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, cid.GetValue());
return CELL_OK;
}
int sys_memory_container_destroy(u32 cid)
{
sc_mem.Warning("sys_memory_container_destroy(cid=%d)", cid);
// Check if this container ID is valid.
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
return CELL_ESRCH;
// Release the allocated memory and remove the ID.
Memory.Free(ct->addr);
Emu.GetIdManager().RemoveID(cid);
return CELL_OK;
}
int sys_memory_container_get_size(u32 mem_info_addr, u32 cid)
{
sc_mem.Warning("sys_memory_container_get_size(mem_info_addr=0x%x, cid=%d)", mem_info_addr, cid);
// Check if this container ID is valid.
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
return CELL_ESRCH;
// HACK: Return all memory.
sys_memory_info info;
info.total_user_memory = re(ct->size);
info.available_user_memory = re(ct->size);
Memory.WriteData(mem_info_addr, info);
return CELL_OK;
}
int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr)
{
sc_mem.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)",
size, flags, alignment, alloc_addr);
if(!Memory.IsGoodAddr(alloc_addr))
return CELL_EFAULT;
// Check for valid alignment.
if(alignment > 0x80000000)
return CELL_EALIGN;
// Check page size.
u32 addr;
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
{
default:
case SYS_MEMORY_PAGE_SIZE_1M:
if(Memory.AlignAddr(size, alignment) & 0xfffff)
return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(Memory.AlignAddr(size, alignment) & 0xffff)
return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
break;
}
// Write back the start address of the allocated area.
Memory.Write32(alloc_addr, addr);
return CELL_OK;
}
int sys_mmapper_allocate_fixed_address()
{
sc_mem.Warning("sys_mmapper_allocate_fixed_address");
// Allocate a fixed size from user memory.
if (!Memory.Alloc(SYS_MMAPPER_FIXED_SIZE, 0x100000))
return CELL_EEXIST;
return CELL_OK;
}
int sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id)
{
sc_mem.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id.GetAddr());
if(!mem_id.IsGood())
return CELL_EFAULT;
// Check page granularity.
u32 addr;
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff)
return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff)
return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
break;
default:
return CELL_EINVAL;
}
if(!addr)
return CELL_ENOMEM;
// Generate a new mem ID.
mem_id = sc_mem.GetNewId(new mmapper_info(addr, size, flags));
return CELL_OK;
}
int sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, mem32_t mem_id)
{
sc_mem.Warning("sys_mmapper_allocate_memory_from_container(size=0x%x, cid=%d, flags=0x%llx, mem_id_addr=0x%x)",
size, cid, flags, mem_id.GetAddr());
if(!mem_id.IsGood())
return CELL_EFAULT;
// Check if this container ID is valid.
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
return CELL_ESRCH;
// Check page granularity.
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff)
return CELL_EALIGN;
ct->addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff)
return CELL_EALIGN;
ct->addr = Memory.Alloc(size, 0x10000);
break;
default:
return CELL_EINVAL;
}
if(!ct->addr)
return CELL_ENOMEM;
ct->size = size;
// Generate a new mem ID.
mem_id = sc_mem.GetNewId(new mmapper_info(ct->addr, ct->size, flags));
return CELL_OK;
}
int sys_mmapper_change_address_access_right(u32 start_addr, u64 flags)
{
sc_mem.Warning("sys_mmapper_change_address_access_right(start_addr=0x%x, flags=0x%llx)", start_addr, flags);
if (!Memory.IsGoodAddr(start_addr))
return CELL_EINVAL;
// TODO
return CELL_OK;
}
int sys_mmapper_free_address(u32 start_addr)
{
sc_mem.Warning("sys_mmapper_free_address(start_addr=0x%x)", start_addr);
if(!Memory.IsGoodAddr(start_addr))
return CELL_EINVAL;
// Free the address.
Memory.Free(start_addr);
return CELL_OK;
}
int sys_mmapper_free_memory(u32 mem_id)
{
sc_mem.Warning("sys_mmapper_free_memory(mem_id=0x%x)", mem_id);
// Check if this mem ID is valid.
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info))
return CELL_ESRCH;
// Release the allocated memory and remove the ID.
Memory.Free(info->addr);
Emu.GetIdManager().RemoveID(mem_id);
return CELL_OK;
}
int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags)
{
sc_mem.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags);
// Check if this mem ID is valid.
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info))
return CELL_ESRCH;
// Map the memory into the process address.
if(!Memory.Map(start_addr, info->addr, info->size))
sc_mem.Error("sys_mmapper_map_memory failed!");
// Keep track of mapped addresses.
mmapper_info_map[mem_id] = start_addr;
return CELL_OK;
}
int sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_addr)
{
sc_mem.Warning("sys_mmapper_search_and_map(start_addr=0x%x, mem_id=0x%x, flags=0x%llx, alloc_addr=0x%x)",
start_addr, mem_id, flags, alloc_addr);
if(!Memory.IsGoodAddr(alloc_addr))
return CELL_EFAULT;
// Check if this mem ID is valid.
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info))
return CELL_ESRCH;
// Search for a mappable address.
u32 addr;
bool found;
for (int i = 0; i < SYS_MMAPPER_FIXED_SIZE; i += 0x100000)
{
addr = start_addr + i;
found = Memory.Map(addr, info->addr, info->size);
if(found)
{
sc_mem.Warning("Found and mapped address 0x%x", addr);
break;
}
}
// Check if the address is valid.
if (!Memory.IsGoodAddr(addr) || !found)
return CELL_ENOMEM;
// Write back the start address of the allocated area.
Memory.Write32(alloc_addr, addr);
// Keep track of mapped addresses.
mmapper_info_map[mem_id] = addr;
return CELL_OK;
}
int sys_mmapper_unmap_memory(u32 start_addr, u32 mem_id_addr)
{
sc_mem.Warning("sys_mmapper_unmap_memory(start_addr=0x%x, mem_id_addr=0x%x)", start_addr, mem_id_addr);
if (!Memory.IsGoodAddr(start_addr))
return CELL_EINVAL;
if (!Memory.IsGoodAddr(mem_id_addr))
return CELL_EFAULT;
// Write back the mem ID of the unmapped area.
u32 mem_id = mmapper_info_map.find(start_addr)->first;
Memory.Write32(mem_id_addr, mem_id);
return CELL_OK;
}
int sys_mmapper_enable_page_fault_notification(u32 start_addr, u32 q_id)
{
sc_mem.Warning("sys_mmapper_enable_page_fault_notification(start_addr=0x%x, q_id=0x%x)", start_addr, q_id);
if (!Memory.IsGoodAddr(start_addr))
return CELL_EINVAL;
// TODO
return CELL_OK;
}

View file

@ -1,6 +1,15 @@
#pragma once #pragma once
#define SYS_MEMORY_CONTAINER_ID_INVALID 0xFFFFFFFF #define SYS_MEMORY_CONTAINER_ID_INVALID 0xFFFFFFFF
#define SYS_MEMORY_ACCESS_RIGHT_NONE 0x00000000000000F0ULL
#define SYS_MEMORY_ACCESS_RIGHT_PPU_THREAD 0x0000000000000008ULL
#define SYS_MEMORY_ACCESS_RIGHT_HANDLER 0x0000000000000004ULL
#define SYS_MEMORY_ACCESS_RIGHT_SPU_THREAD 0x0000000000000002ULL
#define SYS_MEMORY_ACCESS_RIGHT_SPU_RAW 0x0000000000000001ULL
#define SYS_MEMORY_ATTR_READ_ONLY 0x0000000000080000ULL
#define SYS_MEMORY_ATTR_READ_WRITE 0x0000000000040000ULL
#define SYS_MMAPPER_FIXED_ADDR 0xB0000000
#define SYS_MMAPPER_FIXED_SIZE 0x10000000
#define SYS_VM_TEST_INVALID 0x0000ULL #define SYS_VM_TEST_INVALID 0x0000ULL
#define SYS_VM_TEST_UNUSED 0x0001ULL #define SYS_VM_TEST_UNUSED 0x0001ULL
#define SYS_VM_TEST_ALLOCATED 0x0002ULL #define SYS_VM_TEST_ALLOCATED 0x0002ULL
@ -12,6 +21,21 @@ enum
SYS_MEMORY_PAGE_SIZE_64K = 0x200, SYS_MEMORY_PAGE_SIZE_64K = 0x200,
}; };
struct sys_memory_info
{
u32 total_user_memory;
u32 available_user_memory;
};
struct sys_page_attr_t
{
u64 attribute;
u64 access_right;
u32 page_size;
u32 pad;
};
struct MemoryContainerInfo struct MemoryContainerInfo
{ {
u64 addr; u64 addr;
@ -42,12 +66,6 @@ struct mmapper_info
} }
}; };
struct sys_memory_info
{
u32 total_user_memory;
u32 available_user_memory;
};
struct sys_vm_statistics { struct sys_vm_statistics {
u64 vm_crash_ppu; u64 vm_crash_ppu;
u64 vm_crash_spu; u64 vm_crash_spu;
@ -57,11 +75,3 @@ struct sys_vm_statistics {
u32 physical_mem_used; u32 physical_mem_used;
u64 timestamp; u64 timestamp;
}; };
struct sys_page_attr_t
{
u64 attribute;
u64 access_right;
u32 page_size;
u32 pad;
};

View file

@ -98,8 +98,9 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
PPUThread& t = GetCurrentPPUThread(); PPUThread& t = GetCurrentPPUThread();
u32 tid = t.GetId(); u32 tid = t.GetId();
u32 owner = mutex->m_mutex.GetOwner();
_mm_mfence();
u32 owner = mutex->m_mutex.GetOwner();
if (owner == tid) if (owner == tid)
{ {
if (mutex->is_recursive) if (mutex->is_recursive)
@ -119,22 +120,10 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
{ {
if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
{ {
if (!tt->IsAlive())
{
if (owner == mutex->m_mutex.GetOwner()) sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
/*mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
t.owned_mutexes++;
return CELL_OK;*/
}
} }
else else
{ {
sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner); sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
/*mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
t.owned_mutexes++;
return CELL_OK;*/
} }
} }
@ -180,8 +169,9 @@ int sys_mutex_trylock(u32 mutex_id)
PPUThread& t = GetCurrentPPUThread(); PPUThread& t = GetCurrentPPUThread();
u32 tid = t.GetId(); u32 tid = t.GetId();
u32 owner = mutex->m_mutex.GetOwner();
_mm_mfence();
u32 owner = mutex->m_mutex.GetOwner();
if (owner == tid) if (owner == tid)
{ {
if (mutex->is_recursive) if (mutex->is_recursive)
@ -201,22 +191,10 @@ int sys_mutex_trylock(u32 mutex_id)
{ {
if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
{ {
if (!tt->IsAlive())
{
if (owner == mutex->m_mutex.GetOwner()) sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
/*mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
t.owned_mutexes++;
return CELL_OK;*/
}
} }
else else
{ {
sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner); sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
/*mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
t.owned_mutexes++;
return CELL_OK;*/
} }
} }
@ -241,6 +219,7 @@ int sys_mutex_unlock(u32 mutex_id)
PPUThread& t = GetCurrentPPUThread(); PPUThread& t = GetCurrentPPUThread();
u32 tid = t.GetId(); u32 tid = t.GetId();
_mm_mfence();
if (mutex->m_mutex.GetOwner() == tid) if (mutex->m_mutex.GetOwner() == tid)
{ {
if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive)) if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive))

View file

@ -9,32 +9,6 @@
static SysCallBase sc_spu("sys_spu"); static SysCallBase sc_spu("sys_spu");
extern SysCallBase sys_event; extern SysCallBase sys_event;
static const u32 g_spu_group_thr_max = 255;
struct SpuGroupInfo
{
Array<u32> list;
std::atomic<u32> lock;
wxString m_name;
int m_prio;
int m_type;
int m_ct;
SpuGroupInfo(wxString name, u32 num, int prio, int type, u32 ct)
: m_name(name)
, m_prio(prio)
, m_type(type)
, m_ct(ct)
, lock(0)
{
list.SetCount(num);
for (u32 i = 0; i < num; i++)
{
list[i] = 0;
}
}
};
u32 LoadSpuImage(vfsStream& stream, u32& spu_ep) u32 LoadSpuImage(vfsStream& stream, u32& spu_ep)
{ {
ELFLoader l(stream); ELFLoader l(stream);
@ -114,7 +88,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
return CELL_EFAULT; return CELL_EFAULT;
} }
if(spu_num >= g_spu_group_thr_max) if(spu_num >= group_info->list.GetCount())
{ {
return CELL_EINVAL; return CELL_EINVAL;
} }
@ -287,7 +261,7 @@ int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu
if (!Memory.IsGoodAddr(attr->name_addr, attr->name_len)) return CELL_EFAULT; if (!Memory.IsGoodAddr(attr->name_addr, attr->name_len)) return CELL_EFAULT;
if (num > g_spu_group_thr_max) return CELL_EINVAL; if (num > 256) return CELL_EINVAL;
if (prio < 16 || prio > 255) return CELL_EINVAL; if (prio < 16 || prio > 255) return CELL_EINVAL;

View file

@ -55,3 +55,28 @@ struct sys_spu_segment
be_t<int> size; be_t<int> size;
be_t<u64> src; be_t<u64> src;
}; };
struct SpuGroupInfo
{
Array<u32> list;
std::atomic<u32> lock;
wxString m_name;
int m_prio;
int m_type;
int m_ct;
SpuGroupInfo(wxString name, u32 num, int prio, int type, u32 ct)
: m_name(name)
, m_prio(prio)
, m_type(type)
, m_ct(ct)
, lock(0)
{
num = 256;
list.SetCount(num);
for (u32 i = 0; i < num; i++)
{
list[i] = 0;
}
}
};

View file

@ -0,0 +1,51 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/lv2/SC_Spinlock.h"
SysCallBase sys_spinlock("sys_spinlock");
void sys_spinlock_initialize(mem_ptr_t<spinlock> lock)
{
sys_spinlock.Log("sys_spinlock_initialize(lock_addr=0x%x)", lock.GetAddr());
lock->mutex.initialize();
}
void sys_spinlock_lock(mem_ptr_t<spinlock> lock)
{
sys_spinlock.Log("sys_spinlock_lock(lock_addr=0x%x)", lock.GetAddr());
be_t<u32> tid = GetCurrentPPUThread().GetId();
switch (lock->mutex.lock(tid))
{
case SMR_ABORT: ConLog.Warning("sys_spinlock_lock(0x%x) aborted", lock.GetAddr()); break;
case SMR_DEADLOCK: ConLog.Error("sys_spinlock_lock(0x%x) reached deadlock", lock.GetAddr()); break; // ???
default: break;
}
}
int sys_spinlock_trylock(mem_ptr_t<spinlock> lock)
{
sys_spinlock.Log("sys_spinlock_trylock(lock_addr=0x%x)", lock.GetAddr());
be_t<u32> tid = GetCurrentPPUThread().GetId();
switch (lock->mutex.trylock(tid))
{
case SMR_FAILED: return CELL_EBUSY;
case SMR_ABORT: ConLog.Warning("sys_spinlock_trylock(0x%x) aborted", lock.GetAddr()); break;
case SMR_DEADLOCK: ConLog.Error("sys_spinlock_trylock(0x%x) reached deadlock", lock.GetAddr()); break;
default: break;
}
return CELL_OK;
}
void sys_spinlock_unlock(mem_ptr_t<spinlock> lock)
{
sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.GetAddr());
switch (lock->mutex.unlock(lock->mutex.GetOwner()))
{
default: break;
}
}

View file

@ -0,0 +1,6 @@
#pragma once
struct spinlock
{
SMutexBE mutex;
};

View file

@ -93,12 +93,12 @@ bool Emulator::BootGame(const std::string& path)
{ {
static const char* elf_path[6] = static const char* elf_path[6] =
{ {
"\\PS3_GAME\\USRDIR\\BOOT.BIN", "/PS3_GAME/USRDIR/BOOT.BIN",
"\\USRDIR\\BOOT.BIN", "/USRDIR/BOOT.BIN",
"\\BOOT.BIN", "/BOOT.BIN",
"\\PS3_GAME\\USRDIR\\EBOOT.BIN", "/PS3_GAME/USRDIR/EBOOT.BIN",
"\\USRDIR\\EBOOT.BIN", "/USRDIR/EBOOT.BIN",
"\\EBOOT.BIN", "/EBOOT.BIN",
}; };
for(int i=0; i<sizeof(elf_path) / sizeof(*elf_path);i++) for(int i=0; i<sizeof(elf_path) / sizeof(*elf_path);i++)
@ -128,11 +128,11 @@ void Emulator::Load()
if(wxFileName(m_path).GetFullName().CmpNoCase("EBOOT.BIN") == 0) if(wxFileName(m_path).GetFullName().CmpNoCase("EBOOT.BIN") == 0)
{ {
elf_path += "\\BOOT.BIN"; elf_path += "/BOOT.BIN";
} }
else else
{ {
elf_path += "\\" + wxFileName(m_path).GetName() + ".elf"; elf_path += "/" + wxFileName(m_path).GetName() + ".elf";
} }
if(!DecryptSelf(elf_path, self_path)) if(!DecryptSelf(elf_path, self_path))
@ -141,7 +141,7 @@ void Emulator::Load()
m_path = elf_path; m_path = elf_path;
} }
ConLog.Write("Loading '%s'...", m_path.wx_str()); ConLog.Write("Loading '%s'...", m_path.ToStdString().c_str());
GetInfo().Reset(); GetInfo().Reset();
m_vfs.Init(m_path); m_vfs.Init(m_path);
@ -149,7 +149,7 @@ void Emulator::Load()
ConLog.Write("Mount info:"); ConLog.Write("Mount info:");
for(uint i=0; i<m_vfs.m_devices.GetCount(); ++i) for(uint i=0; i<m_vfs.m_devices.GetCount(); ++i)
{ {
ConLog.Write("%s -> %s", m_vfs.m_devices[i].GetPs3Path().wx_str(), m_vfs.m_devices[i].GetLocalPath().wx_str()); ConLog.Write("%s -> %s", m_vfs.m_devices[i].GetPs3Path().ToStdString().c_str(), m_vfs.m_devices[i].GetLocalPath().ToStdString().c_str());
} }
ConLog.SkipLn(); ConLog.SkipLn();
@ -162,7 +162,7 @@ void Emulator::Load()
if(!f.IsOpened()) if(!f.IsOpened())
{ {
ConLog.Error("Elf not found! (%s - %s)", m_path.wx_str(), m_elf_path.wx_str()); ConLog.Error("Elf not found! (%s - %s)", m_path.ToStdString().c_str(), m_elf_path.ToStdString().c_str());
return; return;
} }
@ -441,7 +441,7 @@ void Emulator::LoadPoints(const std::string& path)
if(version != bpdb_version || if(version != bpdb_version ||
(sizeof(u16) + break_count * sizeof(u64) + sizeof(u32) + marked_count * sizeof(u64) + sizeof(u32)) != length) (sizeof(u16) + break_count * sizeof(u64) + sizeof(u32) + marked_count * sizeof(u64) + sizeof(u32)) != length)
{ {
ConLog.Error("'%s' is broken", wxString(path).wx_str()); ConLog.Error("'%s' is broken", path.c_str());
return; return;
} }

View file

@ -45,8 +45,8 @@ AboutDialog::AboutDialog(wxWindow *parent)
//Credits //Credits
wxBoxSizer* s_panel_credits(new wxBoxSizer(wxHORIZONTAL)); wxBoxSizer* s_panel_credits(new wxBoxSizer(wxHORIZONTAL));
wxStaticText* t_section1 = new wxStaticText(this, wxID_ANY, "\nDevelopers:\n\nDH\nAlexAltea\nHykem\nOil", wxDefaultPosition, wxSize(156,160)); wxStaticText* t_section1 = new wxStaticText(this, wxID_ANY, "\nDevelopers:\n\nDH\nAlexAltea\nHykem\nOil\nNekotekina\nelisha464\nBigpet", wxDefaultPosition, wxSize(156,160));
wxStaticText* t_section2 = new wxStaticText(this, wxID_ANY, "\nThanks:\n\nBlackDaemon", wxDefaultPosition, wxSize(156,160)); wxStaticText* t_section2 = new wxStaticText(this, wxID_ANY, "\nThanks:\n\nBlackDaemon\nAishou\nkrofna\nxsacha", wxDefaultPosition, wxSize(156,160));
s_panel_credits->AddSpacer(12); s_panel_credits->AddSpacer(12);
s_panel_credits->Add(t_section1); s_panel_credits->Add(t_section1);

View file

@ -14,6 +14,11 @@ std::mutex g_cs_conlog;
static const uint max_item_count = 500; static const uint max_item_count = 500;
static const uint buffer_size = 1024 * 64; static const uint buffer_size = 1024 * 64;
static const std::string g_log_colors[] =
{
"Black", "Green", "White", "Yellow", "Red",
};
struct LogPacket struct LogPacket
{ {
std::string m_prefix; std::string m_prefix;
@ -112,7 +117,7 @@ LogWriter::LogWriter()
} }
} }
void LogWriter::WriteToLog(std::string prefix, std::string value, std::string colour/*, wxColour bgcolour*/) void LogWriter::WriteToLog(std::string prefix, std::string value, u8 lvl/*, wxColour bgcolour*/)
{ {
if(!prefix.empty()) if(!prefix.empty())
{ {
@ -125,7 +130,8 @@ void LogWriter::WriteToLog(std::string prefix, std::string value, std::string co
if(m_logfile.IsOpened()) if(m_logfile.IsOpened())
m_logfile.Write(wxString(prefix.empty() ? "" : std::string("[" + prefix + "]: ") + value + "\n").wx_str()); m_logfile.Write(wxString(prefix.empty() ? "" : std::string("[" + prefix + "]: ") + value + "\n").wx_str());
if(!ConLogFrame) return; if(!ConLogFrame || Ini.HLELogLvl.GetValue() == 4 || (lvl != 0 && lvl <= Ini.HLELogLvl.GetValue()))
return;
std::lock_guard<std::mutex> lock(g_cs_conlog); std::lock_guard<std::mutex> lock(g_cs_conlog);
@ -156,7 +162,7 @@ void LogWriter::WriteToLog(std::string prefix, std::string value, std::string co
//if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush(); //if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush();
LogBuffer.Push(LogPacket(prefix, value, colour)); LogBuffer.Push(LogPacket(prefix, value, g_log_colors[lvl]));
} }
void LogWriter::Write(const wxString fmt, ...) void LogWriter::Write(const wxString fmt, ...)
@ -169,7 +175,7 @@ void LogWriter::Write(const wxString fmt, ...)
va_end(list); va_end(list);
WriteToLog("!", (const char *)frmt.ToAscii(), "White"); WriteToLog("!", (const char *)frmt.ToAscii(), 2);
} }
void LogWriter::Error(const wxString fmt, ...) void LogWriter::Error(const wxString fmt, ...)
@ -182,7 +188,7 @@ void LogWriter::Error(const wxString fmt, ...)
va_end(list); va_end(list);
WriteToLog("E", static_cast<const char *>(frmt), "Red"); WriteToLog("E", static_cast<const char *>(frmt), 4);
} }
void LogWriter::Warning(const wxString fmt, ...) void LogWriter::Warning(const wxString fmt, ...)
@ -195,7 +201,7 @@ void LogWriter::Warning(const wxString fmt, ...)
va_end(list); va_end(list);
WriteToLog("W", static_cast<const char *>(frmt), "Yellow"); WriteToLog("W", static_cast<const char *>(frmt), 3);
} }
void LogWriter::Success(const wxString fmt, ...) void LogWriter::Success(const wxString fmt, ...)
@ -208,12 +214,12 @@ void LogWriter::Success(const wxString fmt, ...)
va_end(list); va_end(list);
WriteToLog("S", static_cast<const char *>(frmt), "Green"); WriteToLog("S", static_cast<const char *>(frmt), 1);
} }
void LogWriter::SkipLn() void LogWriter::SkipLn()
{ {
WriteToLog("", "", "Black"); WriteToLog("", "", 0);
} }
BEGIN_EVENT_TABLE(LogFrame, wxPanel) BEGIN_EVENT_TABLE(LogFrame, wxPanel)

View file

@ -11,7 +11,7 @@ class LogWriter
std::string m_prefix; std::string m_prefix;
std::string m_value; std::string m_value;
virtual void WriteToLog(std::string prefix, std::string value, std::string colour); virtual void WriteToLog(std::string prefix, std::string value, u8 lvl);
public: public:
LogWriter(); LogWriter();

View file

@ -202,7 +202,7 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event))
} }
else else
{ {
ConLog.Error("Ps3 executable not found in selected folder (%s)", ctrl.GetPath().wx_str()); ConLog.Error("Ps3 executable not found in selected folder (%s)", ctrl.GetPath().ToStdString().c_str());
} }
} }
@ -328,6 +328,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
wxBoxSizer* s_panel(new wxBoxSizer(wxHORIZONTAL)); wxBoxSizer* s_panel(new wxBoxSizer(wxHORIZONTAL));
wxBoxSizer* s_subpanel1(new wxBoxSizer(wxVERTICAL)); wxBoxSizer* s_subpanel1(new wxBoxSizer(wxVERTICAL));
wxBoxSizer* s_subpanel2(new wxBoxSizer(wxVERTICAL)); wxBoxSizer* s_subpanel2(new wxBoxSizer(wxVERTICAL));
wxBoxSizer* s_subpanel3(new wxBoxSizer(wxVERTICAL));
wxStaticBoxSizer* s_round_cpu( new wxStaticBoxSizer( wxVERTICAL, &diag, _("CPU") ) ); wxStaticBoxSizer* s_round_cpu( new wxStaticBoxSizer( wxVERTICAL, &diag, _("CPU") ) );
wxStaticBoxSizer* s_round_cpu_decoder( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Decoder") ) ); wxStaticBoxSizer* s_round_cpu_decoder( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Decoder") ) );
@ -346,6 +347,10 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
wxStaticBoxSizer* s_round_audio_out( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Audio Out") ) ); wxStaticBoxSizer* s_round_audio_out( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Audio Out") ) );
wxStaticBoxSizer* s_round_hle( new wxStaticBoxSizer( wxVERTICAL, &diag, _("HLE / Misc.") ) ); wxStaticBoxSizer* s_round_hle( new wxStaticBoxSizer( wxVERTICAL, &diag, _("HLE / Misc.") ) );
wxStaticBoxSizer* s_round_hle_log_lvl( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Log lvl") ) );
wxStaticBoxSizer* s_round_sys( new wxStaticBoxSizer( wxVERTICAL, &diag, _("System") ) );
wxStaticBoxSizer* s_round_sys_lang( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Language") ) );
wxComboBox* cbox_cpu_decoder = new wxComboBox(&diag, wxID_ANY); wxComboBox* cbox_cpu_decoder = new wxComboBox(&diag, wxID_ANY);
wxComboBox* cbox_gs_render = new wxComboBox(&diag, wxID_ANY); wxComboBox* cbox_gs_render = new wxComboBox(&diag, wxID_ANY);
@ -355,6 +360,8 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
wxComboBox* cbox_keyboard_handler = new wxComboBox(&diag, wxID_ANY); wxComboBox* cbox_keyboard_handler = new wxComboBox(&diag, wxID_ANY);
wxComboBox* cbox_mouse_handler = new wxComboBox(&diag, wxID_ANY); wxComboBox* cbox_mouse_handler = new wxComboBox(&diag, wxID_ANY);
wxComboBox* cbox_audio_out = new wxComboBox(&diag, wxID_ANY); wxComboBox* cbox_audio_out = new wxComboBox(&diag, wxID_ANY);
wxComboBox* cbox_hle_loglvl = new wxComboBox(&diag, wxID_ANY);
wxComboBox* cbox_sys_lang = new wxComboBox(&diag, wxID_ANY);
wxCheckBox* chbox_cpu_ignore_rwerrors = new wxCheckBox(&diag, wxID_ANY, "Ignore Read/Write errors"); wxCheckBox* chbox_cpu_ignore_rwerrors = new wxCheckBox(&diag, wxID_ANY, "Ignore Read/Write errors");
wxCheckBox* chbox_gs_log_prog = new wxCheckBox(&diag, wxID_ANY, "Log vertex/fragment programs"); wxCheckBox* chbox_gs_log_prog = new wxCheckBox(&diag, wxID_ANY, "Log vertex/fragment programs");
@ -397,6 +404,31 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
cbox_audio_out->Append("Null"); cbox_audio_out->Append("Null");
cbox_audio_out->Append("OpenAL"); cbox_audio_out->Append("OpenAL");
cbox_hle_loglvl->Append("All");
cbox_hle_loglvl->Append("Success");
cbox_hle_loglvl->Append("Warnings");
cbox_hle_loglvl->Append("Errors");
cbox_hle_loglvl->Append("Nothing");
cbox_sys_lang->Append("Japanese");
cbox_sys_lang->Append("English (US)");
cbox_sys_lang->Append("French");
cbox_sys_lang->Append("Spanish");
cbox_sys_lang->Append("German");
cbox_sys_lang->Append("Italian");
cbox_sys_lang->Append("Dutch");
cbox_sys_lang->Append("Portuguese (PT)");
cbox_sys_lang->Append("Russian");
cbox_sys_lang->Append("Korean");
cbox_sys_lang->Append("Chinese (Trad.)");
cbox_sys_lang->Append("Chinese (Simp.)");
cbox_sys_lang->Append("Finnish");
cbox_sys_lang->Append("Swedish");
cbox_sys_lang->Append("Danish");
cbox_sys_lang->Append("Norwegian");
cbox_sys_lang->Append("Polish");
cbox_sys_lang->Append("English (UK)");
chbox_cpu_ignore_rwerrors->SetValue(Ini.CPUIgnoreRWErrors.GetValue()); chbox_cpu_ignore_rwerrors->SetValue(Ini.CPUIgnoreRWErrors.GetValue());
chbox_gs_log_prog->SetValue(Ini.GSLogPrograms.GetValue()); chbox_gs_log_prog->SetValue(Ini.GSLogPrograms.GetValue());
chbox_gs_dump_depth->SetValue(Ini.GSDumpDepthBuffer.GetValue()); chbox_gs_dump_depth->SetValue(Ini.GSDumpDepthBuffer.GetValue());
@ -408,6 +440,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
chbox_hle_exitonstop->SetValue(Ini.HLEExitOnStop.GetValue()); chbox_hle_exitonstop->SetValue(Ini.HLEExitOnStop.GetValue());
chbox_audio_dump->Enable(Emu.IsStopped()); chbox_audio_dump->Enable(Emu.IsStopped());
//cbox_audio_out->Enable(Emu.IsStopped());
chbox_hle_logging->Enable(Emu.IsStopped()); chbox_hle_logging->Enable(Emu.IsStopped());
cbox_cpu_decoder->SetSelection(Ini.CPUDecoderMode.GetValue() ? Ini.CPUDecoderMode.GetValue() - 1 : 0); cbox_cpu_decoder->SetSelection(Ini.CPUDecoderMode.GetValue() ? Ini.CPUDecoderMode.GetValue() - 1 : 0);
@ -418,6 +451,8 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
cbox_keyboard_handler->SetSelection(Ini.KeyboardHandlerMode.GetValue()); cbox_keyboard_handler->SetSelection(Ini.KeyboardHandlerMode.GetValue());
cbox_mouse_handler->SetSelection(Ini.MouseHandlerMode.GetValue()); cbox_mouse_handler->SetSelection(Ini.MouseHandlerMode.GetValue());
cbox_audio_out->SetSelection(Ini.AudioOutMode.GetValue()); cbox_audio_out->SetSelection(Ini.AudioOutMode.GetValue());
cbox_hle_loglvl->SetSelection(Ini.HLELogLvl.GetValue());
cbox_sys_lang->SetSelection(Ini.SysLanguage.GetValue());
s_round_cpu_decoder->Add(cbox_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_cpu_decoder->Add(cbox_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_cpu->Add(s_round_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_cpu->Add(s_round_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand());
@ -445,10 +480,15 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
s_round_audio_out->Add(chbox_audio_dump, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_audio_out->Add(chbox_audio_dump, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_audio->Add(s_round_audio_out, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_audio->Add(s_round_audio_out, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_hle_log_lvl->Add(cbox_hle_loglvl, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_hle->Add(s_round_hle_log_lvl, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_hle->Add(chbox_hle_logging, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_hle->Add(chbox_hle_logging, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_hle->Add(chbox_hle_savetty, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_hle->Add(chbox_hle_savetty, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_hle->Add(chbox_hle_exitonstop, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_hle->Add(chbox_hle_exitonstop, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_sys_lang->Add(cbox_sys_lang, wxSizerFlags().Border(wxALL, 5).Expand());
s_round_sys->Add(s_round_sys_lang, wxSizerFlags().Border(wxALL, 5).Expand());
wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL));
s_b_panel->Add(new wxButton(&diag, wxID_OK), wxSizerFlags().Border(wxALL, 5).Center()); s_b_panel->Add(new wxButton(&diag, wxID_OK), wxSizerFlags().Border(wxALL, 5).Center());
@ -462,9 +502,11 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
s_subpanel2->Add(s_round_io, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel2->Add(s_round_io, wxSizerFlags().Border(wxALL, 5).Expand());
s_subpanel2->Add(s_round_audio, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel2->Add(s_round_audio, wxSizerFlags().Border(wxALL, 5).Expand());
s_subpanel2->Add(s_round_hle, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel2->Add(s_round_hle, wxSizerFlags().Border(wxALL, 5).Expand());
s_subpanel3->Add(s_round_sys, wxSizerFlags().Border(wxALL, 5).Expand());
s_panel->Add(s_subpanel1, wxSizerFlags().Border(wxALL, 5).Expand()); s_panel->Add(s_subpanel1, wxSizerFlags().Border(wxALL, 5).Expand());
s_panel->Add(s_subpanel2, wxSizerFlags().Border(wxALL, 5).Expand()); s_panel->Add(s_subpanel2, wxSizerFlags().Border(wxALL, 5).Expand());
s_panel->Add(s_subpanel3, wxSizerFlags().Border(wxALL, 5).Expand());
diag.SetSizerAndFit( s_panel ); diag.SetSizerAndFit( s_panel );
@ -487,6 +529,8 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
Ini.HLELogging.SetValue(chbox_hle_logging->GetValue()); Ini.HLELogging.SetValue(chbox_hle_logging->GetValue());
Ini.HLESaveTTY.SetValue(chbox_hle_savetty->GetValue()); Ini.HLESaveTTY.SetValue(chbox_hle_savetty->GetValue());
Ini.HLEExitOnStop.SetValue(chbox_hle_exitonstop->GetValue()); Ini.HLEExitOnStop.SetValue(chbox_hle_exitonstop->GetValue());
Ini.HLELogLvl.SetValue(cbox_hle_loglvl->GetSelection());
Ini.SysLanguage.SetValue(cbox_sys_lang->GetSelection());
Ini.Save(); Ini.Save();
} }

View file

@ -152,7 +152,7 @@ Ini::Ini()
{ {
#ifdef _WIN32 #ifdef _WIN32
m_Config = new wxIniConfig( wxEmptyString, wxEmptyString, m_Config = new wxIniConfig( wxEmptyString, wxEmptyString,
wxGetCwd() + "\\rpcs3.ini", wxGetCwd() + "/rpcs3.ini",
wxEmptyString, wxCONFIG_USE_LOCAL_FILE ); wxEmptyString, wxCONFIG_USE_LOCAL_FILE );
#else #else
m_Config = new wxConfig("rpcs3"); m_Config = new wxConfig("rpcs3");

View file

@ -109,6 +109,8 @@ public:
IniEntry<bool> HLELogging; IniEntry<bool> HLELogging;
IniEntry<bool> HLESaveTTY; IniEntry<bool> HLESaveTTY;
IniEntry<bool> HLEExitOnStop; IniEntry<bool> HLEExitOnStop;
IniEntry<u8> HLELogLvl;
IniEntry<u8> SysLanguage;
IniEntry<int> PadHandlerLeft; IniEntry<int> PadHandlerLeft;
IniEntry<int> PadHandlerDown; IniEntry<int> PadHandlerDown;
@ -132,11 +134,11 @@ public:
{ {
wxString path; wxString path;
path = DefPath + "\\" + "CPU"; path = DefPath + "/" + "CPU";
CPUDecoderMode.Init("DecoderMode", path); CPUDecoderMode.Init("DecoderMode", path);
CPUIgnoreRWErrors.Init("IgnoreRWErrors", path); CPUIgnoreRWErrors.Init("IgnoreRWErrors", path);
path = DefPath + "\\" + "GS"; path = DefPath + "/" + "GS";
GSRenderMode.Init("RenderMode", path); GSRenderMode.Init("RenderMode", path);
GSResolution.Init("Resolution", path); GSResolution.Init("Resolution", path);
GSAspectRatio.Init("AspectRatio", path); GSAspectRatio.Init("AspectRatio", path);
@ -145,12 +147,12 @@ public:
GSDumpColorBuffers.Init("DumpColorBuffers", path); GSDumpColorBuffers.Init("DumpColorBuffers", path);
GSDumpDepthBuffer.Init("DumpDepthBuffer", path); GSDumpDepthBuffer.Init("DumpDepthBuffer", path);
path = DefPath + "\\" + "IO"; path = DefPath + "/" + "IO";
PadHandlerMode.Init("PadHandlerMode", path); PadHandlerMode.Init("PadHandlerMode", path);
KeyboardHandlerMode.Init("KeyboardHandlerMode", path); KeyboardHandlerMode.Init("KeyboardHandlerMode", path);
MouseHandlerMode.Init("MouseHandlerMode", path); MouseHandlerMode.Init("MouseHandlerMode", path);
path = DefPath + "\\" + "ControlSetings"; path = DefPath + "/" + "ControlSetings";
PadHandlerLeft.Init("PadHandlerLeft", path); PadHandlerLeft.Init("PadHandlerLeft", path);
PadHandlerDown.Init("PadHandlerDown", path); PadHandlerDown.Init("PadHandlerDown", path);
PadHandlerRight.Init("PadHandlerRight", path); PadHandlerRight.Init("PadHandlerRight", path);
@ -168,14 +170,18 @@ public:
PadHandlerR2.Init("PadHandlerR2", path); PadHandlerR2.Init("PadHandlerR2", path);
PadHandlerL2.Init("PadHandlerL2", path); PadHandlerL2.Init("PadHandlerL2", path);
path = DefPath + "\\" + "Audio"; path = DefPath + "/" + "Audio";
AudioOutMode.Init("AudioOutMode", path); AudioOutMode.Init("AudioOutMode", path);
AudioDumpToFile.Init("AudioDumpToFile", path); AudioDumpToFile.Init("AudioDumpToFile", path);
path = DefPath + "\\" + "HLE"; path = DefPath + "/" + "HLE";
HLELogging.Init("HLELogging", path); HLELogging.Init("HLELogging", path);
HLESaveTTY.Init("HLESaveTTY", path); HLESaveTTY.Init("HLESaveTTY", path);
HLEExitOnStop.Init("HLEExitOnStop", path); HLEExitOnStop.Init("HLEExitOnStop", path);
HLELogLvl.Init("HLELogLvl", path);
path = DefPath + "/" + "System";
SysLanguage.Init("SysLanguage", path);
} }
void Load() void Load()
@ -197,6 +203,8 @@ public:
HLELogging.Load(false); HLELogging.Load(false);
HLESaveTTY.Load(false); HLESaveTTY.Load(false);
HLEExitOnStop.Load(false); HLEExitOnStop.Load(false);
HLELogLvl.Load(0);
SysLanguage.Load(1);
PadHandlerLeft.Load(static_cast<int>('A')); PadHandlerLeft.Load(static_cast<int>('A'));
PadHandlerDown.Load(static_cast<int>('S')); PadHandlerDown.Load(static_cast<int>('S'));
@ -235,6 +243,8 @@ public:
HLELogging.Save(); HLELogging.Save();
HLESaveTTY.Save(); HLESaveTTY.Save();
HLEExitOnStop.Save(); HLEExitOnStop.Save();
HLELogLvl.Save();
SysLanguage.Save();
PadHandlerLeft.Save(); PadHandlerLeft.Save();
PadHandlerDown.Save(); PadHandlerDown.Save();

View file

@ -165,7 +165,7 @@ bool Loader::Load()
/* /*
const wxString& root = wxFileName(wxFileName(m_stream->GetPath()).GetPath()).GetPath(); const wxString& root = wxFileName(wxFileName(m_stream->GetPath()).GetPath()).GetPath();
wxString ps3_path; wxString ps3_path;
const wxString& psf_path = root + "\\" + "PARAM.SFO"; const wxString& psf_path = root + "/" + "PARAM.SFO";
vfsFile f(psf_path); vfsFile f(psf_path);
if(f.IsOpened()) if(f.IsOpened())
{ {

View file

@ -5,10 +5,15 @@ TRPLoader::TRPLoader(vfsStream& f) : trp_f(f)
{ {
} }
TRPLoader::~TRPLoader()
{
Close();
}
bool TRPLoader::Install(std::string dest, bool show) bool TRPLoader::Install(std::string dest, bool show)
{ {
if(!trp_f.IsOpened()) return false; if(!trp_f.IsOpened())
if(!LoadHeader(show)) return false; return false;
if (!dest.empty() && dest.back() != '/') if (!dest.empty() && dest.back() != '/')
dest += '/'; dest += '/';
@ -28,13 +33,11 @@ bool TRPLoader::Install(std::string dest, bool show)
return true; return true;
} }
bool TRPLoader::Close()
{
return trp_f.Close();
}
bool TRPLoader::LoadHeader(bool show) bool TRPLoader::LoadHeader(bool show)
{ {
if(!trp_f.IsOpened())
return false;
trp_f.Seek(0); trp_f.Seek(0);
if (trp_f.Read(&m_header, sizeof(TRPHeader)) != sizeof(TRPHeader)) if (trp_f.Read(&m_header, sizeof(TRPHeader)) != sizeof(TRPHeader))
return false; return false;
@ -59,3 +62,36 @@ bool TRPLoader::LoadHeader(bool show)
return true; return true;
} }
bool TRPLoader::ContainsEntry(char *filename)
{
for (const TRPEntry& entry : m_entries) {
if (!strcmp(entry.name, filename))
return true;
}
return false;
}
void TRPLoader::RemoveEntry(char *filename)
{
std::vector<TRPEntry>::iterator i = m_entries.begin();
while (i != m_entries.end()) {
if (!strcmp(i->name, filename))
i = m_entries.erase(i);
else
i++;
}
}
void TRPLoader::RenameEntry(char *oldname, char *newname)
{
for (const TRPEntry& entry : m_entries) {
if (!strcmp(entry.name, oldname))
memcpy((void*)entry.name, newname, 32);
}
}
bool TRPLoader::Close()
{
return trp_f.Close();
}

View file

@ -30,7 +30,13 @@ class TRPLoader
public: public:
TRPLoader(vfsStream& f); TRPLoader(vfsStream& f);
~TRPLoader();
virtual bool Install(std::string dest, bool show = false); virtual bool Install(std::string dest, bool show = false);
virtual bool LoadHeader(bool show = false); virtual bool LoadHeader(bool show = false);
virtual bool ContainsEntry(char *filename);
virtual void RemoveEntry(char *filename);
virtual void RenameEntry(char *oldname, char *newname);
virtual bool Close(); virtual bool Close();
}; };

View file

@ -277,6 +277,7 @@
<ClCompile Include="Emu\SysCalls\lv2\SC_RSX.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_RSX.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Rwlock.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_Rwlock.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Semaphore.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_Semaphore.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Spinlock.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_SPU_Thread.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_SPU_Thread.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Time.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_Time.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Timer.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_Timer.cpp" />
@ -304,6 +305,7 @@
<ClCompile Include="Emu\SysCalls\Modules\cellSysmodule.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\cellSysmodule.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellSysutil.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\cellSysutil.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellSysutilAp.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\cellSysutilAp.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellUserInfo.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellVdec.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\cellVdec.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellVpost.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\cellVpost.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\libmixer.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\libmixer.cpp" />
@ -312,6 +314,7 @@
<ClCompile Include="Emu\SysCalls\Modules\sysPrxForUser.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\sysPrxForUser.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sys_fs.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\sys_fs.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sys_io.cpp" /> <ClCompile Include="Emu\SysCalls\Modules\sys_io.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\sys_net.cpp" />
<ClCompile Include="Emu\SysCalls\Static.cpp" /> <ClCompile Include="Emu\SysCalls\Static.cpp" />
<ClCompile Include="Emu\SysCalls\SysCalls.cpp" /> <ClCompile Include="Emu\SysCalls\SysCalls.cpp" />
<ClCompile Include="Emu\System.cpp" /> <ClCompile Include="Emu\System.cpp" />

View file

@ -460,6 +460,15 @@
<ClCompile Include="Emu\Audio\AL\OpenALThread.cpp"> <ClCompile Include="Emu\Audio\AL\OpenALThread.cpp">
<Filter>Emu\Audio\AL</Filter> <Filter>Emu\Audio\AL</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Emu\SysCalls\Modules\sys_net.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\Modules\cellUserInfo.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\SC_Spinlock.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="rpcs3.rc" /> <ResourceCompile Include="rpcs3.rc" />