Merge pull request #381 from Nekotekina/master

Nekotekina's stuff
This commit is contained in:
B1ackDaemon 2014-07-01 22:06:52 +03:00
commit fd56797b77
29 changed files with 906 additions and 288 deletions

View file

@ -6,6 +6,14 @@
#define thread_local __thread #define thread_local __thread
#endif #endif
template<size_t size>
void strcpy_trunc(char (&dst)[size], const std::string& src)
{
const size_t count = (src.size() >= size) ? size - 1 /* truncation */ : src.size();
memcpy(dst, src.c_str(), count);
dst[count] = 0;
}
#if defined(__GNUG__) #if defined(__GNUG__)
#include <cmath> #include <cmath>
#include <stdlib.h> #include <stdlib.h>

View file

@ -4,8 +4,6 @@ template<typename T, u32 SQSize = 666>
class SQueue class SQueue
{ {
std::mutex m_mutex; std::mutex m_mutex;
NamedThreadBase* push_waiter;
NamedThreadBase* pop_waiter;
u32 m_pos; u32 m_pos;
u32 m_count; u32 m_count;
T m_data[SQSize]; T m_data[SQSize];
@ -14,8 +12,6 @@ public:
SQueue() SQueue()
: m_pos(0) : m_pos(0)
, m_count(0) , m_count(0)
, push_waiter(nullptr)
, pop_waiter(nullptr)
{ {
} }
@ -26,9 +22,6 @@ public:
bool Push(const T& data) bool Push(const T& data)
{ {
NamedThreadBase* t = GetCurrentNamedThread();
push_waiter = t;
while (true) while (true)
{ {
if (m_count >= SQSize) if (m_count >= SQSize)
@ -46,11 +39,9 @@ public:
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (m_count >= SQSize) continue; if (m_count >= SQSize) continue;
if (pop_waiter && !m_count) pop_waiter->Notify();
m_data[(m_pos + m_count++) % SQSize] = data; m_data[(m_pos + m_count++) % SQSize] = data;
push_waiter = nullptr;
return true; return true;
} }
} }
@ -58,9 +49,6 @@ public:
bool Pop(T& data) bool Pop(T& data)
{ {
NamedThreadBase* t = GetCurrentNamedThread();
pop_waiter = t;
while (true) while (true)
{ {
if (!m_count) if (!m_count)
@ -78,43 +66,44 @@ public:
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (!m_count) continue; if (!m_count) continue;
if (push_waiter && m_count >= SQSize) push_waiter->Notify();
data = m_data[m_pos]; data = m_data[m_pos];
m_pos = (m_pos + 1) % SQSize; m_pos = (m_pos + 1) % SQSize;
m_count--; m_count--;
pop_waiter = nullptr;
return true; return true;
} }
} }
} }
volatile u32 GetCount() // may be thread unsafe u32 GetCount()
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_count;
}
u32 GetCountUnsafe()
{ {
return m_count; return m_count;
} }
volatile bool IsEmpty() // may be thread unsafe bool IsEmpty()
{ {
std::lock_guard<std::mutex> lock(m_mutex);
return !m_count; return !m_count;
} }
void Clear() void Clear()
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (push_waiter && m_count >= SQSize) push_waiter->Notify();
m_count = 0; m_count = 0;
} }
T& Peek(u32 pos = 0) T& Peek(u32 pos = 0)
{ {
NamedThreadBase* t = GetCurrentNamedThread();
pop_waiter = t;
while (true) while (true)
{ {
if (!m_count) if (m_count <= pos)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
@ -127,13 +116,27 @@ public:
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (m_count) if (m_count > pos)
{ {
pop_waiter = nullptr;
break; break;
} }
} }
} }
return m_data[(m_pos + pos) % SQSize]; return m_data[(m_pos + pos) % SQSize];
} }
T& PeekIfExist(u32 pos = 0)
{
static T def_value;
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count <= pos)
{
return def_value;
}
else
{
return m_data[(m_pos + pos) % SQSize];
}
}
}; };

View file

@ -257,23 +257,38 @@ struct CellAudioInDeviceConfiguration
u8 reserved[31]; u8 reserved[31];
}; };
enum CellBgmPlaybackStatusState enum CellSysutilBgmPlaybackStatusState
{ {
CELL_BGMPLAYBACK_STATUS_PLAY = 0, CELL_SYSUTIL_BGMPLAYBACK_STATUS_PLAY = 0,
CELL_BGMPLAYBACK_STATUS_STOP = 1 CELL_SYSUTIL_BGMPLAYBACK_STATUS_STOP = 1
}; };
enum CellBgmPlaybackStatusEnabled enum CellSysutilBgmPlaybackStatusEnabled
{ {
CELL_BGMPLAYBACK_STATUS_ENABLE = 0, CELL_SYSUTIL_BGMPLAYBACK_STATUS_ENABLE = 0,
CELL_BGMPLAYBACK_STATUS_DISABLE = 1 CELL_SYSUTIL_BGMPLAYBACK_STATUS_DISABLE = 1
}; };
struct CellBgmPlaybackStatus struct CellSysutilBgmPlaybackStatus
{ {
u8 playbackState; u8 playerState;
u8 enabled; u8 enableState;
char contentId[16]; char contentId[16];
u8 fadeRatio; u8 currentFadeRatio;
char reserved[13]; char reserved[13];
}; };
struct CellSysutilBgmPlaybackStatus2
{
u8 playerState;
char reserved[7];
};
struct CellSysutilBgmPlaybackExtraParam
{
be_t<s32> systemBgmFadeInTime;
be_t<s32> systemBgmFadeOutTime;
be_t<s32> gameBgmFadeInTime;
be_t<s32> gameBgmFadeOutTime;
char reserved[8];
};

View file

@ -115,3 +115,8 @@ bool vfsLocalFile::IsOpened() const
{ {
return m_file.IsOpened() && vfsFileBase::IsOpened(); return m_file.IsOpened() && vfsFileBase::IsOpened();
} }
bool vfsLocalFile::Exists(const std::string& path)
{
return rFileExists(path);
}

View file

@ -12,6 +12,7 @@ public:
virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override; virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override;
virtual bool Create(const std::string& path) override; virtual bool Create(const std::string& path) override;
virtual bool Close() override; virtual bool Close() override;
virtual bool Exists(const std::string& path) override;
virtual u64 GetSize() override; virtual u64 GetSize() override;

View file

@ -623,6 +623,8 @@ enum
NV3089_IMAGE_IN_FORMAT = 0x0000C404, NV3089_IMAGE_IN_FORMAT = 0x0000C404,
NV3089_IMAGE_IN_OFFSET = 0x0000C408, NV3089_IMAGE_IN_OFFSET = 0x0000C408,
NV3089_IMAGE_IN = 0x0000C40C, NV3089_IMAGE_IN = 0x0000C40C,
GCM_SET_USER_COMMAND = 0x0000EB00,
}; };
static const std::string GetMethodName(const u32 id) static const std::string GetMethodName(const u32 id)

View file

@ -355,8 +355,9 @@ bool GLGSRender::LoadProgram()
if(m_fp_buf_num == -1) if(m_fp_buf_num == -1)
{ {
LOG_WARNING(RSX, "FP not found in buffer!"); LOG_WARNING(RSX, "FP not found in buffer!");
m_shader_prog.DecompileAsync(*m_cur_shader_prog); //m_shader_prog.DecompileAsync(*m_cur_shader_prog);
m_shader_prog.Wait(); //m_shader_prog.Wait();
m_shader_prog.Decompile(*m_cur_shader_prog);
m_shader_prog.Compile(); m_shader_prog.Compile();
checkForGlError("m_shader_prog.Compile"); checkForGlError("m_shader_prog.Compile");
@ -367,8 +368,9 @@ bool GLGSRender::LoadProgram()
if(m_vp_buf_num == -1) if(m_vp_buf_num == -1)
{ {
LOG_WARNING(RSX, "VP not found in buffer!"); LOG_WARNING(RSX, "VP not found in buffer!");
m_vertex_prog.DecompileAsync(*m_cur_vertex_prog); //m_vertex_prog.DecompileAsync(*m_cur_vertex_prog);
m_vertex_prog.Wait(); //m_vertex_prog.Wait();
m_vertex_prog.Decompile(*m_cur_vertex_prog);
m_vertex_prog.Compile(); m_vertex_prog.Compile();
checkForGlError("m_vertex_prog.Compile"); checkForGlError("m_vertex_prog.Compile");

View file

@ -251,6 +251,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
//if(cmd == 0xfeadffff) //if(cmd == 0xfeadffff)
{ {
Flip(); Flip();
m_last_flip_time = get_system_time();
m_gcm_current_buffer = ARGS(0); m_gcm_current_buffer = ARGS(0);
m_read_buffer = true; m_read_buffer = true;
@ -2311,6 +2312,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
} }
break; break;
case GCM_SET_USER_COMMAND:
{
const u32 cause = ARGS(0);
m_user_handler.Handle(cause);
m_user_handler.Branch(false);
}
break;
default: default:
{ {
std::string log = GetMethodName(cmd); std::string log = GetMethodName(cmd);
@ -2366,6 +2375,41 @@ void RSXThread::Task()
OnInitThread(); OnInitThread();
m_last_flip_time = get_system_time();
volatile bool is_vblank_stopped = false;
thread vblank("VBlank thread", [&]()
{
const u64 start_time = get_system_time();
m_vblank_count = 0;
while (!TestDestroy())
{
if (Emu.IsStopped())
{
LOG_WARNING(RSX, "VBlank thread aborted");
return;
}
if (get_system_time() - start_time > m_vblank_count * 1000000 / 60)
{
m_vblank_count++;
if (m_vblank_handler)
{
m_vblank_handler.Handle(1);
m_vblank_handler.Branch(false);
}
continue;
}
Sleep(1);
}
is_vblank_stopped = true;
});
vblank.detach();
while(!TestDestroy()) while(!TestDestroy())
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
@ -2457,6 +2501,11 @@ void RSXThread::Task()
//memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4); //memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4);
} }
while (!is_vblank_stopped)
{
Sleep(1);
}
LOG_NOTICE(RSX, "RSX thread ended"); LOG_NOTICE(RSX, "RSX thread ended");
OnExitThread(); OnExitThread();

View file

@ -151,7 +151,11 @@ public:
std::mutex m_cs_main; std::mutex m_cs_main;
SSemaphore m_sem_flush; SSemaphore m_sem_flush;
SSemaphore m_sem_flip; SSemaphore m_sem_flip;
u64 m_last_flip_time;
Callback m_flip_handler; Callback m_flip_handler;
Callback m_user_handler;
u64 m_vblank_count;
Callback m_vblank_handler;
public: public:
// Dither // Dither

View file

@ -32,7 +32,7 @@ int adecRawRead(void* opaque, u8* buf, int buf_size)
next: next:
if (adec.reader.size < (u32)buf_size /*&& !adec.just_started*/) if (adec.reader.size < (u32)buf_size /*&& !adec.just_started*/)
{ {
while (adec.job.IsEmpty()) while (!adec.job.GetCountUnsafe())
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
@ -45,6 +45,7 @@ next:
switch (adec.job.Peek().type) switch (adec.job.Peek().type)
{ {
case adecEndSeq: case adecEndSeq:
case adecClose:
{ {
buf_size = adec.reader.size; buf_size = adec.reader.size;
} }
@ -209,7 +210,7 @@ u32 adecOpen(AudioDecoder* data)
break; break;
} }
if (adec.job.IsEmpty() && adec.is_running) if (!adec.job.GetCountUnsafe() && adec.is_running)
{ {
Sleep(1); Sleep(1);
continue; continue;
@ -255,10 +256,8 @@ u32 adecOpen(AudioDecoder* data)
cb.Branch(true); // ???*/ cb.Branch(true); // ???*/
adec.adecCb->ExecAsCallback(adec.cbFunc, true, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); adec.adecCb->ExecAsCallback(adec.cbFunc, true, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);
avcodec_close(adec.ctx);
avformat_close_input(&adec.fmt);
adec.is_running = false; adec.is_running = false;
adec.just_finished = true;
} }
break; break;
@ -312,7 +311,14 @@ u32 adecOpen(AudioDecoder* data)
dump.Close(); dump.Close();
}*/ }*/
if (adec.just_started) // deferred initialization if (adec.just_started && adec.just_finished)
{
avcodec_flush_buffers(adec.ctx);
adec.reader.init = true;
adec.just_finished = false;
adec.just_started = false;
}
else if (adec.just_started) // deferred initialization
{ {
err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), NULL); err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), NULL);
if (err) if (err)
@ -353,7 +359,7 @@ u32 adecOpen(AudioDecoder* data)
av_dict_set(&opts, "refcounted_frames", "1", 0); av_dict_set(&opts, "refcounted_frames", "1", 0);
{ {
std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2); std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
// not multithread-safe // not multithread-safe (???)
err = avcodec_open2(adec.ctx, codec, &opts); err = avcodec_open2(adec.ctx, codec, &opts);
} }
if (err) if (err)
@ -605,7 +611,7 @@ int cellAdecClose(u32 handle)
adec->job.Push(AdecTask(adecClose)); adec->job.Push(AdecTask(adecClose));
while (!adec->is_finished || !adec->frames.IsEmpty()) while (!adec->is_finished)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
@ -789,13 +795,14 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr)
return CELL_ADEC_ERROR_FATAL; return CELL_ADEC_ERROR_FATAL;
} }
AdecFrame& af = adec->frames.Peek();
if (adec->frames.IsEmpty()) if (adec->frames.IsEmpty())
{ {
Sleep(1); // hack
return CELL_ADEC_ERROR_EMPTY; return CELL_ADEC_ERROR_EMPTY;
} }
AdecFrame& af = adec->frames.Peek();
AVFrame* frame = af.data; AVFrame* frame = af.data;
mem_ptr_t<CellAdecPcmItem> pcm(adec->memAddr + adec->memBias); mem_ptr_t<CellAdecPcmItem> pcm(adec->memAddr + adec->memBias);

View file

@ -1076,6 +1076,7 @@ public:
volatile bool is_running; volatile bool is_running;
volatile bool is_finished; volatile bool is_finished;
bool just_started; bool just_started;
bool just_finished;
AVCodecContext* ctx; AVCodecContext* ctx;
AVFormatContext* fmt; AVFormatContext* fmt;
@ -1127,6 +1128,7 @@ public:
, is_running(false) , is_running(false)
, is_finished(false) , is_finished(false)
, just_started(false) , just_started(false)
, just_finished(false)
, ctx(nullptr) , ctx(nullptr)
, fmt(nullptr) , fmt(nullptr)
{ {
@ -1156,6 +1158,7 @@ public:
~AudioDecoder() ~AudioDecoder()
{ {
// TODO: check finalization
if (ctx) if (ctx)
{ {
for (u32 i = frames.GetCount() - 1; ~i; i--) for (u32 i = frames.GetCount() - 1; ~i; i--)

View file

@ -71,7 +71,7 @@ u32 dmuxOpen(Demuxer* data)
break; break;
} }
if (dmux.job.IsEmpty() && dmux.is_running) if (!dmux.job.GetCountUnsafe() && dmux.is_running)
{ {
// default task (demuxing) (if there is no other work) // default task (demuxing) (if there is no other work)
be_t<u32> code; be_t<u32> code;
@ -145,22 +145,20 @@ u32 dmuxOpen(Demuxer* data)
if (esATX[ch]) if (esATX[ch])
{ {
ElementaryStream& es = *esATX[ch]; ElementaryStream& es = *esATX[ch];
while (es.isfull()) if (es.isfull())
{
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "esATX[%d] was full, waiting aborted", ch);
return;
}
Sleep(1);
}
if (es.hasunseen()) // hack, probably useless
{ {
stream = backup; stream = backup;
Sleep(1);
continue; continue;
} }
/*if (es.hasunseen()) // hack, probably useless
{
stream = backup;
Sleep(1);
continue;
}*/
stream.skip(4); stream.skip(4);
len -= 4; len -= 4;
@ -194,14 +192,10 @@ u32 dmuxOpen(Demuxer* data)
if (esAVC[ch]) if (esAVC[ch])
{ {
ElementaryStream& es = *esAVC[ch]; ElementaryStream& es = *esAVC[ch];
while (es.isfull()) if (es.isfull())
{ {
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "esAVC[%d] was full, waiting aborted", ch);
return;
}
Sleep(1); Sleep(1);
continue;
} }
DemuxerStream backup = stream; DemuxerStream backup = stream;
@ -217,11 +211,12 @@ u32 dmuxOpen(Demuxer* data)
if (pes.new_au && es.hasdata()) // new AU detected if (pes.new_au && es.hasdata()) // new AU detected
{ {
if (es.hasunseen()) // hack, probably useless /*if (es.hasunseen()) // hack, probably useless
{ {
stream = backup; stream = backup;
Sleep(1);
continue; continue;
} }*/
es.finish(stream); es.finish(stream);
// callback // callback
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
@ -242,6 +237,7 @@ u32 dmuxOpen(Demuxer* data)
if (es.isfull()) if (es.isfull())
{ {
stream = backup; stream = backup;
Sleep(1);
continue; continue;
} }

View file

@ -10,152 +10,171 @@
#include "Loader/PSF.h" #include "Loader/PSF.h"
#include "cellGame.h"
//void cellGame_init(); //void cellGame_init();
//Module cellGame(0x003e, cellGame_init); //Module cellGame(0x003e, cellGame_init);
extern Module *cellGame = nullptr; extern Module *cellGame = nullptr;
// Return Codes std::string contentInfo = "";
enum std::string usrdir = "";
{
CELL_GAME_RET_OK = 0,
CELL_GAME_RET_CANCEL = 1,
CELL_GAME_RET_NONE = 2,
CELL_GAME_ERROR_NOTFOUND = 0x8002cb04,
CELL_GAME_ERROR_BROKEN = 0x8002cb05,
CELL_GAME_ERROR_INTERNAL = 0x8002cb06,
CELL_GAME_ERROR_PARAM = 0x8002cb07,
CELL_GAME_ERROR_NOAPP = 0x8002cb08,
CELL_GAME_ERROR_ACCESS_ERROR = 0x8002cb09,
CELL_GAME_ERROR_NOSPACE = 0x8002cb20,
CELL_GAME_ERROR_NOTSUPPORTED = 0x8002cb21,
CELL_GAME_ERROR_FAILURE = 0x8002cb22,
CELL_GAME_ERROR_BUSY = 0x8002cb23,
CELL_GAME_ERROR_IN_SHUTDOWN = 0x8002cb24,
CELL_GAME_ERROR_INVALID_ID = 0x8002cb25,
CELL_GAME_ERROR_EXIST = 0x8002cb26,
CELL_GAME_ERROR_NOTPATCH = 0x8002cb27,
CELL_GAME_ERROR_INVALID_THEME_FILE = 0x8002cb28,
CELL_GAME_ERROR_BOOTPATH = 0x8002cb50,
};
// Definitions
enum
{
CELL_GAME_PATH_MAX = 128,
CELL_GAME_DIRNAME_SIZE = 32,
CELL_GAME_THEMEFILENAME_SIZE = 48,
CELL_GAME_SYSP_TITLE_SIZE = 128,
CELL_GAME_SYSP_TITLEID_SIZE = 10,
CELL_GAME_SYSP_VERSION_SIZE = 6,
CELL_GAME_SYSP_APP_VER_SIZE = 6,
CELL_GAME_GAMETYPE_DISC = 1,
CELL_GAME_GAMETYPE_HDD = 2,
CELL_GAME_SIZEKB_NOTCALC = -1,
CELL_GAME_ATTRIBUTE_PATCH = 0x1,
CELL_GAME_ATTRIBUTE_APP_HOME = 0x2,
CELL_GAME_ATTRIBUTE_DEBUG = 0x4,
CELL_GAME_ATTRIBUTE_XMBBUY = 0x8,
CELL_GAME_ATTRIBUTE_COMMERCE2_BROWSER = 0x10,
CELL_GAME_ATTRIBUTE_INVITE_MESSAGE = 0x20,
CELL_GAME_ATTRIBUTE_CUSTOM_DATA_MESSAGE = 0x40,
CELL_GAME_ATTRIBUTE_WEB_BROWSER = 0x100,
};
//Parameter IDs of PARAM.SFO
enum
{
//Integers
CELL_GAME_PARAMID_PARENTAL_LEVEL = 102,
CELL_GAME_PARAMID_RESOLUTION = 103,
CELL_GAME_PARAMID_SOUND_FORMAT = 104,
//Strings
CELL_GAME_PARAMID_TITLE = 0,
CELL_GAME_PARAMID_TITLE_DEFAULT = 1,
CELL_GAME_PARAMID_TITLE_JAPANESE = 2,
CELL_GAME_PARAMID_TITLE_ENGLISH = 3,
CELL_GAME_PARAMID_TITLE_FRENCH = 4,
CELL_GAME_PARAMID_TITLE_SPANISH = 5,
CELL_GAME_PARAMID_TITLE_GERMAN = 6,
CELL_GAME_PARAMID_TITLE_ITALIAN = 7,
CELL_GAME_PARAMID_TITLE_DUTCH = 8,
CELL_GAME_PARAMID_TITLE_PORTUGUESE = 9,
CELL_GAME_PARAMID_TITLE_RUSSIAN = 10,
CELL_GAME_PARAMID_TITLE_KOREAN = 11,
CELL_GAME_PARAMID_TITLE_CHINESE_T = 12,
CELL_GAME_PARAMID_TITLE_CHINESE_S = 13,
CELL_GAME_PARAMID_TITLE_FINNISH = 14,
CELL_GAME_PARAMID_TITLE_SWEDISH = 15,
CELL_GAME_PARAMID_TITLE_DANISH = 16,
CELL_GAME_PARAMID_TITLE_NORWEGIAN = 17,
CELL_GAME_PARAMID_TITLE_POLISH = 18,
CELL_GAME_PARAMID_TITLE_PORTUGUESE_BRAZIL = 19,
CELL_GAME_PARAMID_TITLE_ENGLISH_UK = 20,
CELL_GAME_PARAMID_TITLE_ID = 100,
CELL_GAME_PARAMID_VERSION = 101,
CELL_GAME_PARAMID_APP_VER = 106,
};
//Error dialog types
enum
{
CELL_GAME_ERRDIALOG_BROKEN_GAMEDATA = 0,
CELL_GAME_ERRDIALOG_BROKEN_HDDGAME = 1,
CELL_GAME_ERRDIALOG_NOSPACE = 2,
CELL_GAME_ERRDIALOG_BROKEN_EXIT_GAMEDATA = 100,
CELL_GAME_ERRDIALOG_BROKEN_EXIT_HDDGAME = 101,
CELL_GAME_ERRDIALOG_NOSPACE_EXIT = 102,
};
struct CellGameContentSize
{
be_t<s32> hddFreeSizeKB;
be_t<s32> sizeKB;
be_t<s32> sysSizeKB;
};
int cellGameBootCheck(mem32_t type, mem32_t attributes, mem_ptr_t<CellGameContentSize> size, mem_list_ptr_t<u8> dirName) int cellGameBootCheck(mem32_t type, mem32_t attributes, mem_ptr_t<CellGameContentSize> size, mem_list_ptr_t<u8> dirName)
{ {
cellGame->Warning("cellGameBootCheck(type_addr=0x%x, attributes_addr=0x%x, size_addr=0x%x, dirName_addr=0x%x)", cellGame->Warning("cellGameBootCheck(type_addr=0x%x, attributes_addr=0x%x, size_addr=0x%x, dirName_addr=0x%x)",
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.GetAddr() && !dirName.IsGood()))
{ {
cellGame->Warning("cellGameBootCheck returns CELL_GAME_ERROR_PARAM. As a result size->hddFreeSizeKB may be 0."); cellGame->Error("cellGameBootCheck(): CELL_GAME_ERROR_PARAM");
return CELL_GAME_ERROR_PARAM; return CELL_GAME_ERROR_PARAM;
} }
// TODO: Only works for HDD games // TODO: Use the free space of the computer's HDD where RPCS3 is being run.
type = CELL_GAME_GAMETYPE_HDD; size->hddFreeSizeKB = 40000000; // 40 GB
attributes = 0;
size->hddFreeSizeKB = 40000000; //40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run. // TODO: Calculate data size for HG and DG games, if necessary.
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"); vfsFile f("/app_home/PARAM.SFO");
if (!f.IsOpened())
{
cellGame->Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR;
}
PSFLoader psf(f); PSFLoader psf(f);
if (!psf.Load(false)) if (!psf.Load(false))
return CELL_GAME_ERROR_FAILURE; {
cellGame->Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR;
}
std::string category = psf.GetString("CATEGORY");
if (category.substr(0, 2) == "DG")
{
type = CELL_GAME_GAMETYPE_DISC;
attributes = 0; // TODO
if (dirName.GetAddr()) Memory.WriteString(dirName.GetAddr(), ""); // ???
contentInfo = "/dev_bdvd/PS3_GAME";
usrdir = "/dev_bdvd/PS3_GAME/USRDIR";
}
else if (category.substr(0, 2) == "HG")
{
std::string titleId = psf.GetString("TITLE_ID"); std::string titleId = psf.GetString("TITLE_ID");
type = CELL_GAME_GAMETYPE_HDD;
Memory.WriteString(dirName.GetAddr(), titleId); attributes = 0; // TODO
return CELL_OK; if (dirName.GetAddr()) Memory.WriteString(dirName.GetAddr(), titleId);
contentInfo = "/dev_hdd0/game/" + titleId;
usrdir = "/dev_hdd0/game/" + titleId + "/USRDIR";
}
else if (category.substr(0, 2) == "GD")
{
std::string titleId = psf.GetString("TITLE_ID");
type = CELL_GAME_GAMETYPE_DISC;
attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
if (dirName.GetAddr()) Memory.WriteString(dirName.GetAddr(), titleId); // ???
contentInfo = "/dev_bdvd/PS3_GAME";
usrdir = "/dev_bdvd/PS3_GAME/USRDIR";
}
else
{
cellGame->Error("cellGameBootCheck(): CELL_GAME_ERROR_FAILURE (unknown CATEGORY)");
return CELL_GAME_ERROR_FAILURE;
} }
int cellGamePatchCheck() return CELL_GAME_RET_OK;
{
UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK;
} }
int cellGameDataCheck() int cellGamePatchCheck(mem_ptr_t<CellGameContentSize> size, u32 reserved_addr)
{ {
UNIMPLEMENTED_FUNC(cellGame); cellGame->Warning("cellGamePatchCheck(size_addr=0x%x, reserved_addr=0x%x)", size.GetAddr(), reserved_addr);
return CELL_OK;
if (!size.IsGood() || reserved_addr != 0)
{
cellGame->Error("cellGamePatchCheck(): CELL_GAME_ERROR_PARAM");
return CELL_GAME_ERROR_PARAM;
}
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
size->hddFreeSizeKB = 40000000; // 40 GB
// TODO: Calculate data size for patch data, if necessary.
size->sizeKB = CELL_GAME_SIZEKB_NOTCALC;
size->sysSizeKB = 0;
vfsFile f("/app_home/PARAM.SFO");
if (!f.IsOpened())
{
cellGame->Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR;
}
PSFLoader psf(f);
if (!psf.Load(false))
{
cellGame->Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR;
}
std::string category = psf.GetString("CATEGORY");
if (category.substr(0, 2) != "GD")
{
cellGame->Error("cellGamePatchCheck(): CELL_GAME_ERROR_NOTPATCH");
return CELL_GAME_ERROR_NOTPATCH;
}
std::string titleId = psf.GetString("TITLE_ID");
contentInfo = "/dev_hdd0/game/" + titleId;
usrdir = "/dev_hdd0/game/" + titleId + "/USRDIR";
return CELL_GAME_RET_OK;
}
int cellGameDataCheck(u32 type, const mem_list_ptr_t<u8> dirName, mem_ptr_t<CellGameContentSize> size)
{
cellGame->Warning("cellGameDataCheck(type=0x%x, dirName_addr=0x%x, size_addr=0x%x)", type, dirName.GetAddr(), size.GetAddr());
if ((type - 1) >= 3 || !size.IsGood() || !dirName.IsGood())
{
cellGame->Error("cellGameDataCheck(): CELL_GAME_ERROR_PARAM");
return CELL_GAME_ERROR_PARAM;
}
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
size->hddFreeSizeKB = 40000000; //40 GB
// TODO: Calculate data size for game data, if necessary.
size->sizeKB = CELL_GAME_SIZEKB_NOTCALC;
size->sysSizeKB = 0;
if (type == CELL_GAME_GAMETYPE_DISC)
{
// TODO: not sure what should be checked there
if (!Emu.GetVFS().ExistsDir("/dev_bdvd/PS3_GAME"))
{
cellGame->Warning("cellGameDataCheck(): /dev_bdvd/PS3_GAME not found");
return CELL_GAME_RET_NONE;
}
contentInfo = "/dev_bdvd/PS3_GAME";
usrdir = "/dev_bdvd/PS3_GAME/USRDIR";
}
else
{
std::string dir = "/dev_hdd0/game/" + std::string(dirName.GetString());
if (!Emu.GetVFS().ExistsDir(dir))
{
cellGame->Warning("cellGameDataCheck(): '%s' directory not found", dir.c_str());
return CELL_GAME_RET_NONE;
}
contentInfo = dir;
usrdir = dir + "/USRDIR";
}
return CELL_GAME_RET_OK;
} }
int cellGameContentPermit(mem_list_ptr_t<u8> contentInfoPath, mem_list_ptr_t<u8> usrdirPath) int cellGameContentPermit(mem_list_ptr_t<u8> contentInfoPath, mem_list_ptr_t<u8> usrdirPath)
@ -164,24 +183,147 @@ int cellGameContentPermit(mem_list_ptr_t<u8> contentInfoPath, mem_list_ptr_t<u8
contentInfoPath.GetAddr(), usrdirPath.GetAddr()); contentInfoPath.GetAddr(), usrdirPath.GetAddr());
if (!contentInfoPath.IsGood() || !usrdirPath.IsGood()) if (!contentInfoPath.IsGood() || !usrdirPath.IsGood())
{
cellGame->Error("cellGameContentPermit(): CELL_GAME_ERROR_PARAM");
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;
std::string titleId = psf.GetString("TITLE_ID");
// TODO: Only works for HDD games
Memory.WriteString(contentInfoPath.GetAddr(), "/dev_hdd0/game/"+titleId);
Memory.WriteString(usrdirPath.GetAddr(), "/dev_hdd0/game/"+titleId+"/USRDIR");
return CELL_OK;
} }
int cellGameCreateGameData() if (contentInfo == "" && usrdir == "")
{ {
UNIMPLEMENTED_FUNC(cellGame); cellGame->Warning("cellGameContentPermit(): CELL_GAME_ERROR_FAILURE (no permission given)");
return CELL_GAME_ERROR_FAILURE;
}
// TODO: make it better
Memory.WriteString(contentInfoPath.GetAddr(), contentInfo);
Memory.WriteString(usrdirPath.GetAddr(), usrdir);
contentInfo = "";
usrdir = "";
return CELL_GAME_RET_OK;
}
int cellGameDataCheckCreate2(u32 version, const mem_list_ptr_t<u8> dirName, u32 errDialog,
mem_func_ptr_t<void(*)(mem_ptr_t<CellGameDataCBResult> cbResult, mem_ptr_t<CellGameDataStatGet> get, mem_ptr_t<CellGameDataStatSet> set)> funcStat, u32 container)
{
cellGame->Warning("cellGameDataCheckCreate2(version=0x%x, dirName_addr=0x%x, errDialog=0x%x, funcStat_addr=0x%x, container=%d)",
version, dirName.GetAddr(), errDialog, funcStat.GetAddr(), container);
if (version != CELL_GAMEDATA_VERSION_CURRENT || !dirName.IsGood() || errDialog > 1 || !funcStat.IsGood())
{
cellGame->Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_PARAM");
return CELL_GAMEDATA_ERROR_PARAM;
}
// TODO: output errors (errDialog)
const std::string dir = "/dev_hdd0/game/" + std::string(dirName.GetString());
if (!Emu.GetVFS().ExistsDir(dir))
{
cellGame->Error("cellGameDataCheckCreate2(): TODO: creating directory '%s'", dir.c_str());
// TODO: create data
return CELL_GAMEDATA_RET_OK;
}
vfsFile f(dir + "/PARAM.SFO");
if (!f.IsOpened())
{
cellGame->Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot open PARAM.SFO)");
return CELL_GAMEDATA_ERROR_BROKEN;
}
PSFLoader psf(f);
if (!psf.Load(false))
{
cellGame->Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot read PARAM.SFO)");
return CELL_GAMEDATA_ERROR_BROKEN;
}
// TODO: use memory container
MemoryAllocator<CellGameDataCBResult> cbResult;
MemoryAllocator<CellGameDataStatGet> cbGet;
MemoryAllocator<CellGameDataStatSet> cbSet;
memset(cbGet.GetPtr(), 0, sizeof(CellGameDataStatGet));
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
cbGet->hddFreeSizeKB = 40000000; //40 GB
cbGet->isNewData = CELL_GAMEDATA_ISNEWDATA_NO;
strcpy_trunc(cbGet->contentInfoPath, dir);
strcpy_trunc(cbGet->gameDataPath, dir + "/USRDIR");
// TODO: set correct time
cbGet->st_atime_ = 0;
cbGet->st_ctime_ = 0;
cbGet->st_mtime_ = 0;
// TODO: calculate data size, if necessary
cbGet->sizeKB = CELL_GAMEDATA_SIZEKB_NOTCALC;
cbGet->sysSizeKB = 0;
cbGet->getParam.attribute = CELL_GAMEDATA_ATTR_NORMAL;
cbGet->getParam.parentalLevel = psf.GetInteger("PARENTAL_LEVEL");
strcpy_trunc(cbGet->getParam.dataVersion, psf.GetString("APP_VER"));
strcpy_trunc(cbGet->getParam.titleId, psf.GetString("TITLE_ID"));
strcpy_trunc(cbGet->getParam.title, psf.GetString("TITLE"));
// TODO: write lang titles
funcStat(cbResult.GetAddr(), cbGet.GetAddr(), cbSet.GetAddr());
if (cbSet->setParam.GetAddr())
{
// TODO: write PARAM.SFO from cbSet
cellGame->Error("cellGameDataCheckCreate2(): TODO: writing PARAM.SFO parameters (addr=0x%x)", cbSet->setParam.GetAddr());
}
switch ((s32)cbResult->result)
{
case CELL_GAMEDATA_CBRESULT_OK_CANCEL:
// TODO: do not process game data
cellGame->Warning("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_OK_CANCEL");
case CELL_GAMEDATA_CBRESULT_OK:
return CELL_GAMEDATA_RET_OK;
case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE: // TODO: process errors, error message and needSizeKB result
cellGame->Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE");
return CELL_GAMEDATA_ERROR_CBRESULT;
case CELL_GAMEDATA_CBRESULT_ERR_BROKEN:
cellGame->Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_BROKEN");
return CELL_GAMEDATA_ERROR_CBRESULT;
case CELL_GAMEDATA_CBRESULT_ERR_NODATA:
cellGame->Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NODATA");
return CELL_GAMEDATA_ERROR_CBRESULT;
case CELL_GAMEDATA_CBRESULT_ERR_INVALID:
cellGame->Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_INVALID");
return CELL_GAMEDATA_ERROR_CBRESULT;
default:
cellGame->Error("cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x)");
return CELL_GAMEDATA_ERROR_CBRESULT;
}
}
int cellGameDataCheckCreate(u32 version, const mem_list_ptr_t<u8> dirName, u32 errDialog,
mem_func_ptr_t<void(*)(mem_ptr_t<CellGameDataCBResult> cbResult, mem_ptr_t<CellGameDataStatGet> get, mem_ptr_t<CellGameDataStatSet> set)> funcStat, u32 container)
{
// TODO: almost identical, the only difference is that this function will always calculate the size of game data
return cellGameDataCheckCreate2(version, dirName, errDialog, funcStat, container);
}
int cellGameCreateGameData(mem_ptr_t<CellGameSetInitParams> init, mem_list_ptr_t<u8> tmp_contentInfoPath, mem_list_ptr_t<u8> tmp_usrdirPath)
{
cellGame->Error("cellGameCreateGameData(init_addr=0x%x, tmp_contentInfoPath_addr=0x%x, tmp_usrdirPath_addr=0x%x)",
init.GetAddr(), tmp_contentInfoPath.GetAddr(), tmp_usrdirPath.GetAddr());
// TODO: create temporary game directory, set initial PARAM.SFO parameters
// cellGameContentPermit should then move files in non-temporary location and return their non-temporary displacement
return CELL_OK; return CELL_OK;
} }
@ -198,7 +340,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 may be wrong. // TODO: Access through cellGame***Check functions
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))
@ -224,7 +366,7 @@ int cellGameGetParamString(u32 id, u32 buf_addr, u32 bufsize)
if(!Memory.IsGoodAddr(buf_addr)) if(!Memory.IsGoodAddr(buf_addr))
return CELL_GAME_ERROR_PARAM; return CELL_GAME_ERROR_PARAM;
// TODO: Locate the PARAM.SFO. The following path may be wrong. // TODO: Access through cellGame***Check functions
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

@ -0,0 +1,202 @@
#pragma once
// Return Codes
enum
{
CELL_GAME_RET_OK = 0,
CELL_GAME_RET_CANCEL = 1,
CELL_GAME_RET_NONE = 2,
CELL_GAME_ERROR_NOTFOUND = 0x8002cb04,
CELL_GAME_ERROR_BROKEN = 0x8002cb05,
CELL_GAME_ERROR_INTERNAL = 0x8002cb06,
CELL_GAME_ERROR_PARAM = 0x8002cb07,
CELL_GAME_ERROR_NOAPP = 0x8002cb08,
CELL_GAME_ERROR_ACCESS_ERROR = 0x8002cb09,
CELL_GAME_ERROR_NOSPACE = 0x8002cb20,
CELL_GAME_ERROR_NOTSUPPORTED = 0x8002cb21,
CELL_GAME_ERROR_FAILURE = 0x8002cb22,
CELL_GAME_ERROR_BUSY = 0x8002cb23,
CELL_GAME_ERROR_IN_SHUTDOWN = 0x8002cb24,
CELL_GAME_ERROR_INVALID_ID = 0x8002cb25,
CELL_GAME_ERROR_EXIST = 0x8002cb26,
CELL_GAME_ERROR_NOTPATCH = 0x8002cb27,
CELL_GAME_ERROR_INVALID_THEME_FILE = 0x8002cb28,
CELL_GAME_ERROR_BOOTPATH = 0x8002cb50,
};
// Definitions
enum
{
CELL_GAME_PATH_MAX = 128,
CELL_GAME_DIRNAME_SIZE = 32,
CELL_GAME_THEMEFILENAME_SIZE = 48,
CELL_GAME_SYSP_LANGUAGE_NUM = 20,
CELL_GAME_SYSP_TITLE_SIZE = 128,
CELL_GAME_SYSP_TITLEID_SIZE = 10,
CELL_GAME_SYSP_VERSION_SIZE = 6,
CELL_GAME_SYSP_APP_VER_SIZE = 6,
CELL_GAME_GAMETYPE_DISC = 1,
CELL_GAME_GAMETYPE_HDD = 2,
CELL_GAME_GAMETYPE_GAMEDATA = 3,
CELL_GAME_SIZEKB_NOTCALC = -1,
CELL_GAME_ATTRIBUTE_PATCH = 0x1,
CELL_GAME_ATTRIBUTE_APP_HOME = 0x2,
CELL_GAME_ATTRIBUTE_DEBUG = 0x4,
CELL_GAME_ATTRIBUTE_XMBBUY = 0x8,
CELL_GAME_ATTRIBUTE_COMMERCE2_BROWSER = 0x10,
CELL_GAME_ATTRIBUTE_INVITE_MESSAGE = 0x20,
CELL_GAME_ATTRIBUTE_CUSTOM_DATA_MESSAGE = 0x40,
CELL_GAME_ATTRIBUTE_WEB_BROWSER = 0x100,
};
//Parameter IDs of PARAM.SFO
enum
{
//Integers
CELL_GAME_PARAMID_PARENTAL_LEVEL = 102,
CELL_GAME_PARAMID_RESOLUTION = 103,
CELL_GAME_PARAMID_SOUND_FORMAT = 104,
//Strings
CELL_GAME_PARAMID_TITLE = 0,
CELL_GAME_PARAMID_TITLE_DEFAULT = 1,
CELL_GAME_PARAMID_TITLE_JAPANESE = 2,
CELL_GAME_PARAMID_TITLE_ENGLISH = 3,
CELL_GAME_PARAMID_TITLE_FRENCH = 4,
CELL_GAME_PARAMID_TITLE_SPANISH = 5,
CELL_GAME_PARAMID_TITLE_GERMAN = 6,
CELL_GAME_PARAMID_TITLE_ITALIAN = 7,
CELL_GAME_PARAMID_TITLE_DUTCH = 8,
CELL_GAME_PARAMID_TITLE_PORTUGUESE = 9,
CELL_GAME_PARAMID_TITLE_RUSSIAN = 10,
CELL_GAME_PARAMID_TITLE_KOREAN = 11,
CELL_GAME_PARAMID_TITLE_CHINESE_T = 12,
CELL_GAME_PARAMID_TITLE_CHINESE_S = 13,
CELL_GAME_PARAMID_TITLE_FINNISH = 14,
CELL_GAME_PARAMID_TITLE_SWEDISH = 15,
CELL_GAME_PARAMID_TITLE_DANISH = 16,
CELL_GAME_PARAMID_TITLE_NORWEGIAN = 17,
CELL_GAME_PARAMID_TITLE_POLISH = 18,
CELL_GAME_PARAMID_TITLE_PORTUGUESE_BRAZIL = 19,
CELL_GAME_PARAMID_TITLE_ENGLISH_UK = 20,
CELL_GAME_PARAMID_TITLE_ID = 100,
CELL_GAME_PARAMID_VERSION = 101,
CELL_GAME_PARAMID_APP_VER = 106,
};
//Error dialog types
enum
{
CELL_GAME_ERRDIALOG_BROKEN_GAMEDATA = 0,
CELL_GAME_ERRDIALOG_BROKEN_HDDGAME = 1,
CELL_GAME_ERRDIALOG_NOSPACE = 2,
CELL_GAME_ERRDIALOG_BROKEN_EXIT_GAMEDATA = 100,
CELL_GAME_ERRDIALOG_BROKEN_EXIT_HDDGAME = 101,
CELL_GAME_ERRDIALOG_NOSPACE_EXIT = 102,
};
struct CellGameContentSize
{
be_t<s32> hddFreeSizeKB;
be_t<s32> sizeKB;
be_t<s32> sysSizeKB;
};
struct CellGameSetInitParams
{
char title[CELL_GAME_SYSP_TITLE_SIZE];
char titleId[CELL_GAME_SYSP_TITLEID_SIZE];
char reserved0[2];
char version[CELL_GAME_SYSP_VERSION_SIZE];
char reserved1[66];
};
struct CellGameDataCBResult
{
be_t<s32> result;
be_t<s32> errNeedSizeKB;
be_t<u32> invalidMsg_addr;
be_t<u32> reserved;
};
enum // old consts
{
CELL_GAMEDATA_CBRESULT_OK_CANCEL = 1,
CELL_GAMEDATA_CBRESULT_OK = 0,
CELL_GAMEDATA_CBRESULT_ERR_NOSPACE = -1,
CELL_GAMEDATA_CBRESULT_ERR_BROKEN = -3,
CELL_GAMEDATA_CBRESULT_ERR_NODATA = -4,
CELL_GAMEDATA_CBRESULT_ERR_INVALID = -5,
CELL_GAMEDATA_RET_OK = 0,
CELL_GAMEDATA_RET_CANCEL = 1,
CELL_GAMEDATA_ERROR_CBRESULT = 0x8002b601,
CELL_GAMEDATA_ERROR_ACCESS_ERROR = 0x8002b602,
CELL_GAMEDATA_ERROR_INTERNAL = 0x8002b603,
CELL_GAMEDATA_ERROR_PARAM = 0x8002b604,
CELL_GAMEDATA_ERROR_NOSPACE = 0x8002b605,
CELL_GAMEDATA_ERROR_BROKEN = 0x8002b606,
CELL_GAMEDATA_ERROR_FAILURE = 0x8002b607,
CELL_GAMEDATA_ATTR_NORMAL = 0,
CELL_GAMEDATA_VERSION_CURRENT = 0,
CELL_GAMEDATA_INVALIDMSG_MAX = 256,
CELL_GAMEDATA_PATH_MAX = 1055,
CELL_GAMEDATA_DIRNAME_SIZE = 32,
CELL_GAMEDATA_SIZEKB_NOTCALC = -1,
CELL_GAMEDATA_SYSP_LANGUAGE_NUM = 20,
CELL_GAMEDATA_SYSP_TITLE_SIZE = 128,
CELL_GAMEDATA_SYSP_TITLEID_SIZE = 10,
CELL_GAMEDATA_SYSP_VERSION_SIZE = 6,
CELL_GAMEDATA_ISNEWDATA_NO = 0,
CELL_GAMEDATA_ISNEWDATA_YES = 1,
CELL_GAMEDATA_ERRDIALOG_NONE = 0,
CELL_GAMEDATA_ERRDIALOG_ALWAYS = 1,
};
struct CellGameDataSystemFileParam
{
char title[CELL_GAMEDATA_SYSP_TITLE_SIZE];
char titleLang[CELL_GAMEDATA_SYSP_LANGUAGE_NUM][CELL_GAMEDATA_SYSP_TITLE_SIZE];
char titleId[CELL_GAMEDATA_SYSP_TITLEID_SIZE];
char reserved0[2];
char dataVersion[CELL_GAMEDATA_SYSP_VERSION_SIZE];
char reserved1[2];
be_t<u32> parentalLevel;
be_t<u32> attribute;
char reserved2[256];
};
struct CellGameDataStatGet
{
be_t<s32> hddFreeSizeKB;
be_t<u32> isNewData;
char contentInfoPath[CELL_GAMEDATA_PATH_MAX];
char gameDataPath[CELL_GAMEDATA_PATH_MAX];
char reserved0[2];
be_t<s64> st_atime_;
be_t<s64> st_mtime_;
be_t<s64> st_ctime_;
CellGameDataSystemFileParam getParam;
be_t<s32> sizeKB;
be_t<s32> sysSizeKB;
char reserved1[68];
};
struct CellGameDataStatSet
{
mem_beptr_t<CellGameDataSystemFileParam> setParam;
be_t<u32> reserved;
};

View file

@ -421,18 +421,16 @@ int cellGcmSetFlip(mem_ptr_t<CellGcmContextData> ctxt, u32 id)
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK;
} }
int cellGcmSetFlipHandler(u32 handler_addr) void cellGcmSetFlipHandler(u32 handler_addr)
{ {
cellGcmSys->Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler_addr); cellGcmSys->Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler_addr);
if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr)) if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr))
{ {
cellGcmSys->Error("cellGcmSetFlipHandler : CELL_EFAULT"); cellGcmSys->Error("cellGcmSetFlipHandler(handler_addr=%d): invalid address", handler_addr);
return CELL_EFAULT;
} }
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr); Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr);
return CELL_OK;
} }
int cellGcmSetFlipMode(u32 mode) int cellGcmSetFlipMode(u32 mode)
@ -567,16 +565,28 @@ int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
return CELL_OK; return CELL_OK;
} }
u32 cellGcmSetUserHandler(u32 handler) void cellGcmSetUserHandler(u32 handler_addr)
{ {
cellGcmSys->Warning("cellGcmSetUserHandler(handler=0x%x)", handler); cellGcmSys->Warning("cellGcmSetUserHandler(handler_addr=0x%x)", handler_addr);
return handler;
if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr))
{
cellGcmSys->Error("cellGcmSetUserHandler(handler_addr=%d): invalid address", handler_addr);
} }
int cellGcmSetVBlankHandler() Emu.GetGSManager().GetRender().m_user_handler.SetAddr(handler_addr);
}
void cellGcmSetVBlankHandler(u32 handler_addr)
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); cellGcmSys->Warning("cellGcmSetVBlankHandler(handler_addr=0x%x)", handler_addr);
return CELL_OK;
if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr))
{
cellGcmSys->Error("cellGcmSetVBlankHandler(handler_addr=%d): invalid address", handler_addr);
}
Emu.GetGSManager().GetRender().m_vblank_handler.SetAddr(handler_addr);
} }
int cellGcmSetWaitFlip(mem_ptr_t<CellGcmContextData> ctxt) int cellGcmSetWaitFlip(mem_ptr_t<CellGcmContextData> ctxt)
@ -699,10 +709,11 @@ int cellGcmGetDisplayBufferByFlipIndex()
return CELL_OK; return CELL_OK;
} }
int cellGcmgetLastFlipTime() u64 cellGcmGetLastFlipTime()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); cellGcmSys->Log("cellGcmGetLastFlipTime()");
return CELL_OK;
return Emu.GetGSManager().GetRender().m_last_flip_time;
} }
int cellGcmGetLastSecondVTime() int cellGcmGetLastSecondVTime()
@ -711,10 +722,11 @@ int cellGcmGetLastSecondVTime()
return CELL_OK; return CELL_OK;
} }
int cellGcmGetVBlankCount() u64 cellGcmGetVBlankCount()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); cellGcmSys->Log("cellGcmGetVBlankCount()");
return CELL_OK;
return Emu.GetGSManager().GetRender().m_vblank_count;
} }
int cellGcmInitSystemMode() int cellGcmInitSystemMode()
@ -1156,7 +1168,7 @@ void cellGcmSys_init()
cellGcmSys->AddFunc(0xe315a0b2, cellGcmGetConfiguration); cellGcmSys->AddFunc(0xe315a0b2, cellGcmGetConfiguration);
cellGcmSys->AddFunc(0x371674cf, cellGcmGetDisplayBufferByFlipIndex); cellGcmSys->AddFunc(0x371674cf, cellGcmGetDisplayBufferByFlipIndex);
cellGcmSys->AddFunc(0x72a577ce, cellGcmGetFlipStatus); cellGcmSys->AddFunc(0x72a577ce, cellGcmGetFlipStatus);
cellGcmSys->AddFunc(0x63387071, cellGcmgetLastFlipTime); cellGcmSys->AddFunc(0x63387071, cellGcmGetLastFlipTime);
cellGcmSys->AddFunc(0x23ae55a3, cellGcmGetLastSecondVTime); cellGcmSys->AddFunc(0x23ae55a3, cellGcmGetLastSecondVTime);
cellGcmSys->AddFunc(0x055bd74d, cellGcmGetTiledPitchSize); cellGcmSys->AddFunc(0x055bd74d, cellGcmGetTiledPitchSize);
cellGcmSys->AddFunc(0x723bbc7e, cellGcmGetVBlankCount); cellGcmSys->AddFunc(0x723bbc7e, cellGcmGetVBlankCount);

View file

@ -93,6 +93,23 @@ int cellPngDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t<CellPngDecSrc> s
return CELL_OK; return CELL_OK;
} }
int cellPngDecExtOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t<CellPngDecSrc> src, u32 openInfo, mem_ptr_t<CellPngDecCbCtrlStrm> cbCtrlStrm, mem_ptr_t<CellPngDecOpnParam> opnParam)
{
cellPngDec->Warning("cellPngDecExtOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x, cbCtrlStrm_addr=0x%x, opnParam=0x%x)",
mainHandle, subHandle.GetAddr(), src.GetAddr(), openInfo, cbCtrlStrm.GetAddr(), opnParam.GetAddr());
cellPngDec->Warning("*** cbCtrlStrm->cbCtrlStrmFunc_addr=0x%x", cbCtrlStrm->cbCtrlStrmFunc.GetAddr());
MemoryAllocator<CellPngDecStrmInfo> streamInfo;
MemoryAllocator<CellPngDecStrmParam> streamParam;
int res = cellPngDecOpen(mainHandle, subHandle, src, openInfo);
if (!res) cbCtrlStrm->cbCtrlStrmFunc(streamInfo.GetAddr(), streamParam.GetAddr(), cbCtrlStrm->cbCtrlStrmArg);
return res;
}
int cellPngDecClose(u32 mainHandle, u32 subHandle) int cellPngDecClose(u32 mainHandle, u32 subHandle)
{ {
cellPngDec->Warning("cellPngDecClose(mainHandle=0x%x,subHandle=0x%x)", mainHandle, subHandle); cellPngDec->Warning("cellPngDecClose(mainHandle=0x%x,subHandle=0x%x)", mainHandle, subHandle);
@ -112,7 +129,7 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellPngDecInfo
if (!info.IsGood()) if (!info.IsGood())
return CELL_PNGDEC_ERROR_ARG; return CELL_PNGDEC_ERROR_ARG;
cellPngDec->Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%llx)", mainHandle, subHandle, info.GetAddr()); cellPngDec->Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", mainHandle, subHandle, info.GetAddr());
CellPngDecSubHandle* subHandle_data; CellPngDecSubHandle* subHandle_data;
if(!cellPngDec->CheckId(subHandle, subHandle_data)) if(!cellPngDec->CheckId(subHandle, subHandle_data))
return CELL_PNGDEC_ERROR_FATAL; return CELL_PNGDEC_ERROR_FATAL;
@ -167,6 +184,14 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellPngDecInfo
return CELL_OK; return CELL_OK;
} }
int cellPngDecExtReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellPngDecInfo> info, mem_ptr_t<CellPngDecExtInfo> extInfo)
{
cellPngDec->Warning("cellPngDecExtReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x, extInfo_addr=0x%x)",
mainHandle, subHandle, info.GetAddr(), extInfo.GetAddr());
return cellPngDecReadHeader(mainHandle, subHandle, info);
}
int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_ptr_t<CellPngDecDataCtrlParam> dataCtrlParam, mem_ptr_t<CellPngDecDataOutInfo> dataOutInfo) int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_ptr_t<CellPngDecDataCtrlParam> dataCtrlParam, mem_ptr_t<CellPngDecDataOutInfo> dataOutInfo)
{ {
if (!data.IsGood() || !dataCtrlParam.IsGood() || !dataOutInfo.IsGood()) if (!data.IsGood() || !dataCtrlParam.IsGood() || !dataOutInfo.IsGood())
@ -292,6 +317,17 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m
return CELL_OK; return CELL_OK;
} }
int cellPngDecExtDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_ptr_t<CellPngDecDataCtrlParam> dataCtrlParam,
mem_ptr_t<CellPngDecDataOutInfo> dataOutInfo, mem_ptr_t<CellPngDecCbCtrlDisp> cbCtrlDisp, mem_ptr_t<CellPngDecDispParam> dispParam)
{
cellPngDec->Warning("cellPngDecExtDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x, cbCtrlDisp_addr=0x%x, dispParam=0x%x",
mainHandle, subHandle, data.GetAddr(), dataCtrlParam.GetAddr(), dataOutInfo.GetAddr(), cbCtrlDisp.GetAddr(), dispParam.GetAddr());
if (cbCtrlDisp.GetAddr()) cellPngDec->Warning("*** cbCtrlDisp->cbCtrlDispFunc_addr=0x%x", (u32)cbCtrlDisp->cbCtrlDispFunc_addr);
return cellPngDecDecodeData(mainHandle, subHandle, data, dataCtrlParam, dataOutInfo);
}
int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, const mem_ptr_t<CellPngDecInParam> inParam, mem_ptr_t<CellPngDecOutParam> outParam) int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, const mem_ptr_t<CellPngDecInParam> inParam, mem_ptr_t<CellPngDecOutParam> outParam)
{ {
if (!inParam.IsGood() || !outParam.IsGood()) if (!inParam.IsGood() || !outParam.IsGood())
@ -333,6 +369,15 @@ int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, const mem_ptr_t<CellPn
return CELL_OK; return CELL_OK;
} }
int cellPngDecExtSetParameter(u32 mainHandle, u32 subHandle, const mem_ptr_t<CellPngDecInParam> inParam, mem_ptr_t<CellPngDecOutParam> outParam,
mem_ptr_t<CellPngDecExtInParam> extInParam, mem_ptr_t<CellPngDecExtOutParam> extOutParam)
{
cellPngDec->Warning("cellPngDecExtSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x, extInParam=0x%x, extOutParam=0x%x",
mainHandle, subHandle, inParam.GetAddr(), outParam.GetAddr(), extInParam.GetAddr(), extOutParam.GetAddr());
return cellPngDecSetParameter(mainHandle, subHandle, inParam, outParam);
}
void cellPngDec_init() void cellPngDec_init()
{ {
cellPngDec->AddFunc(0x157d30c5, cellPngDecCreate); cellPngDec->AddFunc(0x157d30c5, cellPngDecCreate);
@ -343,11 +388,12 @@ void cellPngDec_init()
cellPngDec->AddFunc(0x2310f155, cellPngDecDecodeData); cellPngDec->AddFunc(0x2310f155, cellPngDecDecodeData);
cellPngDec->AddFunc(0xe97c9bd4, cellPngDecSetParameter); cellPngDec->AddFunc(0xe97c9bd4, cellPngDecSetParameter);
/*cellPngDec->AddFunc(0x48436b2d, cellPngDecExtCreate);
cellPngDec->AddFunc(0x0c515302, cellPngDecExtOpen); cellPngDec->AddFunc(0x0c515302, cellPngDecExtOpen);
cellPngDec->AddFunc(0x8b33f863, cellPngDecExtReadHeader); cellPngDec->AddFunc(0x8b33f863, cellPngDecExtReadHeader);
cellPngDec->AddFunc(0x726fc1d0, cellPngDecExtDecodeData); cellPngDec->AddFunc(0x726fc1d0, cellPngDecExtDecodeData);
cellPngDec->AddFunc(0x9e9d7d42, cellPngDecExtSetParameter); cellPngDec->AddFunc(0x9e9d7d42, cellPngDecExtSetParameter);
/*cellPngDec->AddFunc(0x48436b2d, cellPngDecExtCreate);
cellPngDec->AddFunc(0x7585a275, cellPngDecGetbKGD); cellPngDec->AddFunc(0x7585a275, cellPngDecGetbKGD);
cellPngDec->AddFunc(0x7a062d26, cellPngDecGetcHRM); cellPngDec->AddFunc(0x7a062d26, cellPngDecGetcHRM);
cellPngDec->AddFunc(0xb153629c, cellPngDecGetgAMA); cellPngDec->AddFunc(0xb153629c, cellPngDecGetgAMA);

View file

@ -124,3 +124,54 @@ struct CellPngDecMainHandle
be_t<u32> threadInParam; be_t<u32> threadInParam;
be_t<u32> threadOutParam; be_t<u32> threadOutParam;
}; };
struct CellPngDecStrmInfo
{
be_t<u32> decodedStrmSize;
};
struct CellPngDecStrmParam
{
be_t<u32> strmPtr;
be_t<u32> strmSize;
};
struct CellPngDecCbCtrlStrm
{
mem_func_beptr_t<void(*)(mem_ptr_t<CellPngDecStrmInfo> strmInfo, mem_ptr_t<CellPngDecStrmParam> strmParam, u32 cbCtrlStrmArg)> cbCtrlStrmFunc;
be_t<u32> cbCtrlStrmArg;
};
struct CellPngDecCbCtrlDisp
{
be_t<u32> cbCtrlDispFunc_addr;
be_t<u32> cbCtrlDispArg;
};
struct CellPngDecDispParam
{
be_t<u32> nextOutputImage_addr;
};
struct CellPngDecExtInfo
{
be_t<u64> reserved;
};
struct CellPngDecExtInParam
{
be_t<u32> bufferMode; // CellPngDecBufferMode
be_t<u32> outputCounts;
be_t<u32> spuMode; // CellPngDecSpuMode
};
struct CellPngDecExtOutParam
{
be_t<u64> outputWidthByte;
be_t<u32> outputHeight;
};
struct CellPngDecOpnParam
{
be_t<u32> selectChunk;
};

View file

@ -88,13 +88,13 @@ CCellRescInternal* s_rescInternalInstance = nullptr;
// Extern Functions // Extern Functions
extern int cellGcmSetFlipMode(u32 mode); extern int cellGcmSetFlipMode(u32 mode);
extern int cellGcmSetFlipHandler(u32 handler_addr); extern void cellGcmSetFlipHandler(u32 handler_addr);
extern s32 cellGcmAddressToOffset(u64 address, mem32_t offset); extern int cellGcmAddressToOffset(u64 address, mem32_t offset);
extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height); extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height);
extern int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctx, u32 id); extern int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctx, u32 id);
extern int cellGcmSetSecondVFrequency(u32 freq); extern int cellGcmSetSecondVFrequency(u32 freq);
extern u32 cellGcmGetLabelAddress(u8 index); extern u32 cellGcmGetLabelAddress(u8 index);
extern u32 cellGcmSetVBlankHandler(u32 handler); extern void cellGcmSetVBlankHandler(u32 handler);
extern u32 cellGcmSetSecondVHandler(u32 handler); extern u32 cellGcmSetSecondVHandler(u32 handler);
extern u32 cellGcmGetTiledPitchSize(u32 size); extern u32 cellGcmGetTiledPitchSize(u32 size);
@ -1096,19 +1096,16 @@ int cellRescSetBufferAddress(mem32_t colorBuffers, mem32_t vertexArray, mem32_t
return CELL_OK; return CELL_OK;
} }
int cellRescSetFlipHandler(u32 handler_addr) void cellRescSetFlipHandler(u32 handler_addr)
{ {
cellResc->Warning("cellRescSetFlipHandler(handler_addr=0x%x)", handler_addr); cellResc->Warning("cellRescSetFlipHandler(handler_addr=0x%x)", handler_addr);
if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr)) if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr))
{ {
cellResc->Error("cellRescSetFlipHandler : CELL_EFAULT"); cellResc->Error("cellRescSetFlipHandler(handler_addr=%d): invalid address", handler_addr);
return CELL_EFAULT;
} }
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr); Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr);
return CELL_OK;
} }
void cellRescResetFlipStatus() void cellRescResetFlipStatus()
@ -1131,10 +1128,11 @@ int cellRescGetRegisterCount()
return CELL_OK; return CELL_OK;
} }
int cellRescGetLastFlipTime() u64 cellRescGetLastFlipTime()
{ {
UNIMPLEMENTED_FUNC(cellResc); cellResc->Log("cellRescGetLastFlipTime()");
return CELL_OK;
return Emu.GetGSManager().GetRender().m_last_flip_time;
} }
int cellRescSetRegisterCount() int cellRescSetRegisterCount()
@ -1143,10 +1141,16 @@ int cellRescSetRegisterCount()
return CELL_OK; return CELL_OK;
} }
int cellRescSetVBlankHandler() void cellRescSetVBlankHandler(u32 handler_addr)
{ {
UNIMPLEMENTED_FUNC(cellResc); cellResc->Warning("cellRescSetVBlankHandler(handler_addr=0x%x)", handler_addr);
return CELL_OK;
if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr))
{
cellResc->Error("cellRescSetVBlankHandler(handler_addr=%d): invalid address", handler_addr);
}
Emu.GetGSManager().GetRender().m_vblank_handler.SetAddr(handler_addr);
} }
u16 FloatToHalf(float val) u16 FloatToHalf(float val)

View file

@ -10,6 +10,7 @@
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellSysutil_SaveData.h" #include "cellSysutil_SaveData.h"
#include "cellGame.h"
#include "Loader/PSF.h" #include "Loader/PSF.h"
@ -380,8 +381,11 @@ int cellSysutilUnregisterCallback(int slot)
return CELL_OK; return CELL_OK;
} }
int cellMsgDialogOpen2(u32 type, char* msgString, mem_func_ptr_t<CellMsgDialogCallback> callback, mem_ptr_t<void> userData, u32 extParam) int cellMsgDialogOpen2(u32 type, mem_list_ptr_t<u8> msgString, mem_func_ptr_t<CellMsgDialogCallback> callback, mem_ptr_t<void> userData, u32 extParam)
{ {
cellSysutil->Warning("cellMsgDialogOpen2(type=0x%x, msgString_addr=0x%x, callback_addr=0x%x, userData=0x%x, extParam=0x%x)",
type, msgString.GetAddr(), callback.GetAddr(), userData.GetAddr(), extParam);
long style = 0; long style = 0;
if(type & CELL_MSGDIALOG_DIALOG_TYPE_NORMAL) if(type & CELL_MSGDIALOG_DIALOG_TYPE_NORMAL)
@ -402,7 +406,7 @@ int cellMsgDialogOpen2(u32 type, char* msgString, mem_func_ptr_t<CellMsgDialogCa
style |= rOK; style |= rOK;
} }
int res = rMessageBox(std::string(msgString), rGetApp().GetAppName(), style); int res = rMessageBox(std::string(msgString.GetString()), rGetApp().GetAppName(), style);
u64 status; u64 status;
@ -919,21 +923,23 @@ int cellHddGameCheck(u32 version, u32 dirName_addr, u32 errDialog, mem_func_ptr_
return CELL_OK; return CELL_OK;
} }
bool bgm_playback_enabled = false; bool bgm_playback_enabled = true;
int cellSysutilEnableBgmPlayback() int cellSysutilEnableBgmPlayback()
{ {
cellSysutil->Warning("cellSysutilEnableBgmPlayback()"); cellSysutil->Warning("cellSysutilEnableBgmPlayback()");
// TODO
bgm_playback_enabled = true; bgm_playback_enabled = true;
return CELL_OK; return CELL_OK;
} }
int cellSysutilEnableBgmPlaybackEx() int cellSysutilEnableBgmPlaybackEx(mem_ptr_t<CellSysutilBgmPlaybackExtraParam> param)
{ {
cellSysutil->Warning("cellSysutilEnableBgmPlaybackEx()"); cellSysutil->Warning("cellSysutilEnableBgmPlaybackEx(param_addr=0x%x)", param.GetAddr());
// TODO
bgm_playback_enabled = true; bgm_playback_enabled = true;
return CELL_OK; return CELL_OK;
@ -943,42 +949,43 @@ int cellSysutilDisableBgmPlayback()
{ {
cellSysutil->Warning("cellSysutilDisableBgmPlayback()"); cellSysutil->Warning("cellSysutilDisableBgmPlayback()");
// TODO
bgm_playback_enabled = false; bgm_playback_enabled = false;
return CELL_OK; return CELL_OK;
} }
int cellSysutilDisableBgmPlaybackEx() int cellSysutilDisableBgmPlaybackEx(mem_ptr_t<CellSysutilBgmPlaybackExtraParam> param)
{ {
cellSysutil->Warning("cellSysutilDisableBgmPlaybackEx()"); cellSysutil->Warning("cellSysutilDisableBgmPlaybackEx(param_addr=0x%x)", param.GetAddr());
bgm_playback_enabled = false;
return CELL_OK;
}
int cellSysutilGetBgmPlaybackStatus(mem_ptr_t<CellBgmPlaybackStatus> status)
{
cellSysutil->Warning("cellSysutilGetBgmPlaybackStatus(status=0x%x)", status.GetAddr());
// TODO // TODO
status->playbackState = CELL_BGMPLAYBACK_STATUS_STOP; bgm_playback_enabled = false;
status->enabled = bgm_playback_enabled ? CELL_BGMPLAYBACK_STATUS_ENABLE : CELL_BGMPLAYBACK_STATUS_DISABLE;
status->fadeRatio = 0; // volume ratio return CELL_OK;
}
int cellSysutilGetBgmPlaybackStatus(mem_ptr_t<CellSysutilBgmPlaybackStatus> status)
{
cellSysutil->Log("cellSysutilGetBgmPlaybackStatus(status_addr=0x%x)", status.GetAddr());
// TODO
status->playerState = CELL_SYSUTIL_BGMPLAYBACK_STATUS_STOP;
status->enableState = bgm_playback_enabled ? CELL_SYSUTIL_BGMPLAYBACK_STATUS_ENABLE : CELL_SYSUTIL_BGMPLAYBACK_STATUS_DISABLE;
status->currentFadeRatio = 0; // current volume ratio (0%)
memset(status->contentId, 0, sizeof(status->contentId)); memset(status->contentId, 0, sizeof(status->contentId));
memset(status->reserved, 0, sizeof(status->reserved));
return CELL_OK; return CELL_OK;
} }
int cellSysutilGetBgmPlaybackStatus2(mem_ptr_t<CellBgmPlaybackStatus> status2) int cellSysutilGetBgmPlaybackStatus2(mem_ptr_t<CellSysutilBgmPlaybackStatus2> status2)
{ {
cellSysutil->Warning("cellSysutilGetBgmPlaybackStatus2(status=0x%x)", status2.GetAddr()); cellSysutil->Log("cellSysutilGetBgmPlaybackStatus2(status2_addr=0x%x)", status2.GetAddr());
// TODO // TODO
status2->playbackState = CELL_BGMPLAYBACK_STATUS_STOP; status2->playerState = CELL_SYSUTIL_BGMPLAYBACK_STATUS_STOP;
status2->enabled = bgm_playback_enabled ? CELL_BGMPLAYBACK_STATUS_ENABLE : CELL_BGMPLAYBACK_STATUS_DISABLE; memset(status2->reserved, 0, sizeof(status2->reserved));
status2->fadeRatio = 0; // volume ratio
memset(status2->contentId, 0, sizeof(status2->contentId));
return CELL_OK; return CELL_OK;
} }
@ -991,6 +998,12 @@ int cellWebBrowserEstimate2(mem8_ptr_t _config, mem32_ptr_t memSize)
return CELL_OK; return CELL_OK;
} }
extern int cellGameDataCheckCreate2(u32 version, const mem_list_ptr_t<u8> dirName, u32 errDialog,
mem_func_ptr_t<void(*)(mem_ptr_t<CellGameDataCBResult> cbResult, mem_ptr_t<CellGameDataStatGet> get, mem_ptr_t<CellGameDataStatSet> set)> funcStat, u32 container);
extern int cellGameDataCheckCreate(u32 version, const mem_list_ptr_t<u8> dirName, u32 errDialog,
mem_func_ptr_t<void(*)(mem_ptr_t<CellGameDataCBResult> cbResult, mem_ptr_t<CellGameDataStatGet> get, mem_ptr_t<CellGameDataStatSet> set)> funcStat, u32 container);
void cellSysutil_init() void cellSysutil_init()
{ {
cellSysutil->AddFunc(0x40e895d3, cellSysutilGetSystemParamInt); cellSysutil->AddFunc(0x40e895d3, cellSysutilGetSystemParamInt);
@ -1068,4 +1081,7 @@ void cellSysutil_init()
//cellSysutil->AddFunc(0xe7fa820b, cellSaveDataEnableOverlay); //cellSysutil->AddFunc(0xe7fa820b, cellSaveDataEnableOverlay);
cellSysutil->AddFunc(0x6d087930, cellWebBrowserEstimate2); cellSysutil->AddFunc(0x6d087930, cellWebBrowserEstimate2);
cellSysutil->AddFunc(0xe7951dee, cellGameDataCheckCreate);
cellSysutil->AddFunc(0xc9645c41, cellGameDataCheckCreate2);
} }

View file

@ -31,7 +31,7 @@ int vdecRead(void* opaque, u8* buf, int buf_size)
next: next:
if (vdec.reader.size < (u32)buf_size /*&& !vdec.just_started*/) if (vdec.reader.size < (u32)buf_size /*&& !vdec.just_started*/)
{ {
while (vdec.job.IsEmpty()) while (!vdec.job.GetCountUnsafe())
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
@ -44,6 +44,7 @@ next:
switch (vdec.job.Peek().type) switch (vdec.job.Peek().type)
{ {
case vdecEndSeq: case vdecEndSeq:
case vdecClose:
{ {
buf_size = vdec.reader.size; buf_size = vdec.reader.size;
} }
@ -147,7 +148,7 @@ u32 vdecOpen(VideoDecoder* data)
break; break;
} }
if (vdec.job.IsEmpty() && vdec.is_running) if (!vdec.job.GetCountUnsafe() && vdec.is_running)
{ {
Sleep(1); Sleep(1);
continue; continue;
@ -189,10 +190,8 @@ u32 vdecOpen(VideoDecoder* data)
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
cb.Branch(true); // ???*/ cb.Branch(true); // ???*/
avcodec_close(vdec.ctx);
avformat_close_input(&vdec.fmt);
vdec.is_running = false; vdec.is_running = false;
vdec.just_finished = true;
} }
break; break;
@ -244,7 +243,13 @@ u32 vdecOpen(VideoDecoder* data)
} au(0); } au(0);
if (vdec.just_started) // deferred initialization if (vdec.just_started && vdec.just_finished)
{
avcodec_flush_buffers(vdec.ctx);
vdec.just_started = false;
vdec.just_finished = false;
}
else if (vdec.just_started) // deferred initialization
{ {
err = avformat_open_input(&vdec.fmt, NULL, av_find_input_format("mpeg"), NULL); err = avformat_open_input(&vdec.fmt, NULL, av_find_input_format("mpeg"), NULL);
if (err) if (err)
@ -285,7 +290,7 @@ u32 vdecOpen(VideoDecoder* data)
av_dict_set(&opts, "refcounted_frames", "1", 0); av_dict_set(&opts, "refcounted_frames", "1", 0);
{ {
std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2); std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
// not multithread-safe // not multithread-safe (???)
err = avcodec_open2(vdec.ctx, codec, &opts); err = avcodec_open2(vdec.ctx, codec, &opts);
} }
if (err) if (err)
@ -294,8 +299,6 @@ u32 vdecOpen(VideoDecoder* data)
Emu.Pause(); Emu.Pause();
break; break;
} }
//vdec.ctx->flags |= CODEC_FLAG_TRUNCATED;
//vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS;
vdec.just_started = false; vdec.just_started = false;
} }
@ -303,8 +306,9 @@ u32 vdecOpen(VideoDecoder* data)
while (true) while (true)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped() || vdec.job.PeekIfExist().type == vdecClose)
{ {
vdec.is_finished = true;
LOG_WARNING(HLE, "vdecDecodeAu: aborted"); LOG_WARNING(HLE, "vdecDecodeAu: aborted");
return; return;
} }
@ -498,7 +502,7 @@ int cellVdecClose(u32 handle)
vdec->job.Push(VdecTask(vdecClose)); vdec->job.Push(VdecTask(vdecClose));
while (!vdec->is_finished || !vdec->frames.IsEmpty()) while (!vdec->is_finished)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
@ -674,14 +678,14 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr)
return CELL_VDEC_ERROR_FATAL; return CELL_VDEC_ERROR_FATAL;
} }
VdecFrame& vf = vdec->frames.Peek();
if (vdec->frames.IsEmpty()) if (vdec->frames.IsEmpty())
{ {
Sleep(1); Sleep(1); // hack
return CELL_VDEC_ERROR_EMPTY; return CELL_VDEC_ERROR_EMPTY;
} }
VdecFrame& vf = vdec->frames.Peek();
AVFrame& frame = *vf.data; AVFrame& frame = *vf.data;
mem_ptr_t<CellVdecPicItem> info(vdec->memAddr + vdec->memBias); mem_ptr_t<CellVdecPicItem> info(vdec->memAddr + vdec->memBias);

View file

@ -647,6 +647,7 @@ struct CellVdecMpeg2Info
enum VdecJobType : u32 enum VdecJobType : u32
{ {
vdecInvalid,
vdecStartSeq, vdecStartSeq,
vdecEndSeq, vdecEndSeq,
vdecDecodeAu, vdecDecodeAu,
@ -675,6 +676,7 @@ struct VdecTask
} }
VdecTask() VdecTask()
: type(vdecInvalid)
{ {
} }
}; };
@ -697,6 +699,7 @@ public:
volatile bool is_running; volatile bool is_running;
volatile bool is_finished; volatile bool is_finished;
bool just_started; bool just_started;
bool just_finished;
AVCodecContext* ctx; AVCodecContext* ctx;
AVFormatContext* fmt; AVFormatContext* fmt;
@ -735,6 +738,7 @@ public:
, is_finished(false) , is_finished(false)
, is_running(false) , is_running(false)
, just_started(false) , just_started(false)
, just_finished(false)
, ctx(nullptr) , ctx(nullptr)
, vdecCb(nullptr) , vdecCb(nullptr)
{ {
@ -764,6 +768,7 @@ public:
~VideoDecoder() ~VideoDecoder()
{ {
// TODO: check finalization
if (ctx) if (ctx)
{ {
for (u32 i = frames.GetCount() - 1; ~i; i--) for (u32 i = frames.GetCount() - 1; ~i; i--)

View file

@ -30,6 +30,12 @@ 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); sceNp->Warning("sceNpDrmIsAvailable(k_licensee_addr=0x%x, drm_path_addr=0x%x)", k_licensee_addr, drm_path_addr);
std::string drm_path = Memory.ReadString(drm_path_addr); std::string drm_path = Memory.ReadString(drm_path_addr);
if (!Emu.GetVFS().ExistsFile(drm_path))
{
sceNp->Warning("sceNpDrmIsAvailable(): '%s' not found", drm_path.c_str());
return CELL_ENOENT;
}
std::string k_licensee_str; std::string k_licensee_str;
u8 k_licensee[0x10]; u8 k_licensee[0x10];
for(int i = 0; i < 0x10; i++) for(int i = 0; i < 0x10; i++)

View file

@ -114,16 +114,16 @@ int sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil
int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
{ {
const std::string& path = Memory.ReadString(path_addr); const std::string& path = Memory.ReadString(path_addr);
sys_fs->Warning("cellFsSdataOpen(path=\"%s\", flags=0x%x, fd_addr=0x%x, arg_addr=0x%x, size=0x%llx)", sys_fs->Warning("cellFsSdataOpen(path=\"%s\", flags=0x%x, fd_addr=0x%x, arg_addr=0x%x, size=0x%llx) -> cellFsOpen()",
path.c_str(), flags, fd.GetAddr(), arg.GetAddr(), size); path.c_str(), flags, fd.GetAddr(), arg.GetAddr(), size);
if (!fd.IsGood() || (!arg.IsGood() && size)) /*if (!fd.IsGood() || (!arg.IsGood() && size))
return CELL_EFAULT; return CELL_EFAULT;
if (flags != CELL_O_RDONLY) if (flags != CELL_O_RDONLY)
return CELL_EINVAL; return CELL_EINVAL;
std::string suffix = path.substr(path.length() - 5, 4); std::string suffix = path.substr(path.length() - 5, 5);
if (suffix != ".sdat" && suffix != ".SDAT") if (suffix != ".sdat" && suffix != ".SDAT")
return CELL_ENOTSDATA; return CELL_ENOTSDATA;
@ -135,7 +135,9 @@ int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
fd = sys_fs->GetNewId(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), flags); fd = sys_fs->GetNewId(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), flags);
return CELL_OK; return CELL_OK;*/
return cellFsOpen(path_addr, flags, fd, arg, size);
} }
std::atomic<u32> g_FsAioReadID( 0 ); std::atomic<u32> g_FsAioReadID( 0 );

View file

@ -142,8 +142,6 @@ int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u64
{ {
SMutexLocker lock(ef->m_mutex); SMutexLocker lock(ef->m_mutex);
ef->signal.unlock(tid);
u64 flags = ef->flags; u64 flags = ef->flags;
for (u32 i = 0; i < ef->waiters.size(); i++) for (u32 i = 0; i < ef->waiters.size(); i++)
@ -161,6 +159,17 @@ int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u64
ef->flags = 0; ef->flags = 0;
} }
if (u32 target = ef->check())
{
// if signal, leave both mutexes locked...
ef->signal.unlock(tid, target);
ef->m_mutex.unlock(tid, target);
}
else
{
ef->signal.unlock(tid);
}
if (result.IsGood()) if (result.IsGood())
{ {
result = flags; result = flags;
@ -175,6 +184,7 @@ int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u64
} }
} }
ef->signal.unlock(tid);
return CELL_ECANCELED; return CELL_ECANCELED;
} }

View file

@ -116,6 +116,12 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
return CELL_EINVAL; return CELL_EINVAL;
} }
if (!Emu.GetVFS().ExistsFile(ppath))
{
sys_fs->Error("\"%s\" not found! flags: 0x%08x", ppath.c_str(), flags);
return CELL_ENOENT;
}
vfsFileBase* stream = Emu.GetVFS().OpenFile(ppath, o_mode); vfsFileBase* stream = Emu.GetVFS().OpenFile(ppath, o_mode);
if(!stream || !stream->IsOpened()) if(!stream || !stream->IsOpened())
@ -126,7 +132,7 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
} }
fd = sys_fs->GetNewId(stream, IDFlag_File); fd = sys_fs->GetNewId(stream, IDFlag_File);
LOG_WARNING(HLE, "*** cellFsOpen(path=\"%s\"): fd = %d", path.c_str(), fd.GetValue()); LOG_WARNING(HLE, "\"%s\" opened: fd = %d", path.c_str(), fd.GetValue());
return CELL_OK; return CELL_OK;
} }

View file

@ -11,6 +11,7 @@
#include "Emu/Cell/SPUThread.h" #include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/PPUInstrTable.h" #include "Emu/Cell/PPUInstrTable.h"
#include "Emu/FS/vfsFile.h" #include "Emu/FS/vfsFile.h"
#include "Emu/FS/vfsDeviceLocalFile.h"
#include "Emu/CPU/CPUThreadManager.h" //gui dependency #include "Emu/CPU/CPUThreadManager.h" //gui dependency
@ -163,6 +164,18 @@ void Emulator::Load()
{ {
LOG_NOTICE(LOADER, "%s -> %s", m_vfs.m_devices[i]->GetPs3Path().c_str(), m_vfs.m_devices[i]->GetLocalPath().c_str()); LOG_NOTICE(LOADER, "%s -> %s", m_vfs.m_devices[i]->GetPs3Path().c_str(), m_vfs.m_devices[i]->GetLocalPath().c_str());
} }
// bdvd inserting imitation
vfsFile f1("/app_home/dev_bdvd.path");
if (f1.IsOpened())
{
std::string bdvd;
bdvd.resize(f1.GetSize());
f1.Read(&bdvd[0], bdvd.size());
// load desired /dev_bdvd/ real directory and remount
Emu.GetVFS().Mount("/dev_bdvd/", bdvd, new vfsDeviceLocalFile());
LOG_NOTICE(LOADER, "/dev_bdvd/ remounted into %s", bdvd.c_str());
}
LOG_NOTICE(LOADER, " ");//used to be skip_line LOG_NOTICE(LOADER, " ");//used to be skip_line
if(m_elf_path.empty()) if(m_elf_path.empty())

View file

@ -88,7 +88,7 @@ struct wxWriter : Log::LogListener
default: default:
break; break;
} }
llogcon->AppendText(wxString(msg.mText)); llogcon->AppendText(fmt::FromUTF8(msg.mText));
} }
} }
if (m_log->GetLastPosition() > GUI_BUFFER_MAX_SIZE) if (m_log->GetLastPosition() > GUI_BUFFER_MAX_SIZE)

View file

@ -339,6 +339,7 @@
<ClInclude Include="Emu\SysCalls\Modules\cellAtrac.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellAtrac.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellDmux.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellDmux.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellFont.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellFont.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellGame.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellGifDec.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellGifDec.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellJpgDec.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellJpgDec.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellPamf.h" /> <ClInclude Include="Emu\SysCalls\Modules\cellPamf.h" />

View file

@ -1072,5 +1072,8 @@
<ClInclude Include="..\Utilities\Log.h"> <ClInclude Include="..\Utilities\Log.h">
<Filter>Utilities</Filter> <Filter>Utilities</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\SysCalls\Modules\cellGame.h">
<Filter>Emu\SysCalls\Modules</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>