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
#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__)
#include <cmath>
#include <stdlib.h>

View file

@ -4,8 +4,6 @@ template<typename T, u32 SQSize = 666>
class SQueue
{
std::mutex m_mutex;
NamedThreadBase* push_waiter;
NamedThreadBase* pop_waiter;
u32 m_pos;
u32 m_count;
T m_data[SQSize];
@ -14,8 +12,6 @@ public:
SQueue()
: m_pos(0)
, m_count(0)
, push_waiter(nullptr)
, pop_waiter(nullptr)
{
}
@ -26,9 +22,6 @@ public:
bool Push(const T& data)
{
NamedThreadBase* t = GetCurrentNamedThread();
push_waiter = t;
while (true)
{
if (m_count >= SQSize)
@ -46,11 +39,9 @@ public:
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count >= SQSize) continue;
if (pop_waiter && !m_count) pop_waiter->Notify();
m_data[(m_pos + m_count++) % SQSize] = data;
push_waiter = nullptr;
return true;
}
}
@ -58,9 +49,6 @@ public:
bool Pop(T& data)
{
NamedThreadBase* t = GetCurrentNamedThread();
pop_waiter = t;
while (true)
{
if (!m_count)
@ -78,43 +66,44 @@ public:
std::lock_guard<std::mutex> lock(m_mutex);
if (!m_count) continue;
if (push_waiter && m_count >= SQSize) push_waiter->Notify();
data = m_data[m_pos];
m_pos = (m_pos + 1) % SQSize;
m_count--;
pop_waiter = nullptr;
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;
}
volatile bool IsEmpty() // may be thread unsafe
bool IsEmpty()
{
std::lock_guard<std::mutex> lock(m_mutex);
return !m_count;
}
void Clear()
{
std::lock_guard<std::mutex> lock(m_mutex);
if (push_waiter && m_count >= SQSize) push_waiter->Notify();
m_count = 0;
}
T& Peek(u32 pos = 0)
{
NamedThreadBase* t = GetCurrentNamedThread();
pop_waiter = t;
while (true)
{
if (!m_count)
if (m_count <= pos)
{
if (Emu.IsStopped())
{
@ -127,13 +116,27 @@ public:
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count)
if (m_count > pos)
{
pop_waiter = nullptr;
break;
}
}
}
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];
};
enum CellBgmPlaybackStatusState
enum CellSysutilBgmPlaybackStatusState
{
CELL_BGMPLAYBACK_STATUS_PLAY = 0,
CELL_BGMPLAYBACK_STATUS_STOP = 1
CELL_SYSUTIL_BGMPLAYBACK_STATUS_PLAY = 0,
CELL_SYSUTIL_BGMPLAYBACK_STATUS_STOP = 1
};
enum CellBgmPlaybackStatusEnabled
enum CellSysutilBgmPlaybackStatusEnabled
{
CELL_BGMPLAYBACK_STATUS_ENABLE = 0,
CELL_BGMPLAYBACK_STATUS_DISABLE = 1
CELL_SYSUTIL_BGMPLAYBACK_STATUS_ENABLE = 0,
CELL_SYSUTIL_BGMPLAYBACK_STATUS_DISABLE = 1
};
struct CellBgmPlaybackStatus
struct CellSysutilBgmPlaybackStatus
{
u8 playbackState;
u8 enabled;
u8 playerState;
u8 enableState;
char contentId[16];
u8 fadeRatio;
u8 currentFadeRatio;
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();
}
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 Create(const std::string& path) override;
virtual bool Close() override;
virtual bool Exists(const std::string& path) override;
virtual u64 GetSize() override;

View file

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

View file

@ -355,8 +355,9 @@ bool GLGSRender::LoadProgram()
if(m_fp_buf_num == -1)
{
LOG_WARNING(RSX, "FP not found in buffer!");
m_shader_prog.DecompileAsync(*m_cur_shader_prog);
m_shader_prog.Wait();
//m_shader_prog.DecompileAsync(*m_cur_shader_prog);
//m_shader_prog.Wait();
m_shader_prog.Decompile(*m_cur_shader_prog);
m_shader_prog.Compile();
checkForGlError("m_shader_prog.Compile");
@ -367,8 +368,9 @@ bool GLGSRender::LoadProgram()
if(m_vp_buf_num == -1)
{
LOG_WARNING(RSX, "VP not found in buffer!");
m_vertex_prog.DecompileAsync(*m_cur_vertex_prog);
m_vertex_prog.Wait();
//m_vertex_prog.DecompileAsync(*m_cur_vertex_prog);
//m_vertex_prog.Wait();
m_vertex_prog.Decompile(*m_cur_vertex_prog);
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)
{
Flip();
m_last_flip_time = get_system_time();
m_gcm_current_buffer = ARGS(0);
m_read_buffer = true;
@ -2311,6 +2312,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
}
break;
case GCM_SET_USER_COMMAND:
{
const u32 cause = ARGS(0);
m_user_handler.Handle(cause);
m_user_handler.Branch(false);
}
break;
default:
{
std::string log = GetMethodName(cmd);
@ -2366,6 +2375,41 @@ void RSXThread::Task()
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())
{
if (Emu.IsStopped())
@ -2457,6 +2501,11 @@ void RSXThread::Task()
//memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4);
}
while (!is_vblank_stopped)
{
Sleep(1);
}
LOG_NOTICE(RSX, "RSX thread ended");
OnExitThread();

View file

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

View file

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

View file

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

View file

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

View file

@ -10,178 +10,320 @@
#include "Loader/PSF.h"
#include "cellGame.h"
//void cellGame_init();
//Module cellGame(0x003e, cellGame_init);
extern Module *cellGame = nullptr;
// 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_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;
};
std::string contentInfo = "";
std::string usrdir = "";
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)",
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;
}
// TODO: Only works for HDD games
type = CELL_GAME_GAMETYPE_HDD;
attributes = 0;
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->sysSizeKB = 0;
// 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 HG and DG games, if necessary.
size->sizeKB = CELL_GAME_SIZEKB_NOTCALC;
size->sysSizeKB = 0;
// TODO: Locate the PARAM.SFO. The following path may be wrong.
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);
if(!psf.Load(false))
if (!psf.Load(false))
{
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");
type = CELL_GAME_GAMETYPE_HDD;
attributes = 0; // TODO
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;
}
return CELL_GAME_RET_OK;
}
int cellGamePatchCheck(mem_ptr_t<CellGameContentSize> size, u32 reserved_addr)
{
cellGame->Warning("cellGamePatchCheck(size_addr=0x%x, reserved_addr=0x%x)", size.GetAddr(), reserved_addr);
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");
Memory.WriteString(dirName.GetAddr(), titleId);
return CELL_OK;
contentInfo = "/dev_hdd0/game/" + titleId;
usrdir = "/dev_hdd0/game/" + titleId + "/USRDIR";
return CELL_GAME_RET_OK;
}
int cellGamePatchCheck()
int cellGameDataCheck(u32 type, const mem_list_ptr_t<u8> dirName, mem_ptr_t<CellGameContentSize> size)
{
UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK;
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 cellGameDataCheck()
{
UNIMPLEMENTED_FUNC(cellGame);
return CELL_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)
{
cellGame->Warning("cellGameContentPermit(contentInfoPath_addr=0x%x, usrdirPath_addr=0x%x)",
contentInfoPath.GetAddr(), usrdirPath.GetAddr());
if (!contentInfoPath.IsGood() || !usrdirPath.IsGood())
{
cellGame->Error("cellGameContentPermit(): 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;
if (contentInfo == "" && usrdir == "")
{
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 cellGameCreateGameData()
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)
{
UNIMPLEMENTED_FUNC(cellGame);
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;
}
@ -198,7 +340,7 @@ int cellGameGetParamInt(u32 id, mem32_t value)
if(!value.IsGood())
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");
PSFLoader psf(f);
if(!psf.Load(false))
@ -224,7 +366,7 @@ int cellGameGetParamString(u32 id, u32 buf_addr, u32 bufsize)
if(!Memory.IsGoodAddr(buf_addr))
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");
PSFLoader psf(f);
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;
}
int cellGcmSetFlipHandler(u32 handler_addr)
void cellGcmSetFlipHandler(u32 handler_addr)
{
cellGcmSys->Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler_addr);
if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr))
{
cellGcmSys->Error("cellGcmSetFlipHandler : CELL_EFAULT");
return CELL_EFAULT;
cellGcmSys->Error("cellGcmSetFlipHandler(handler_addr=%d): invalid address", handler_addr);
}
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr);
return CELL_OK;
}
int cellGcmSetFlipMode(u32 mode)
@ -567,16 +565,28 @@ int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
return CELL_OK;
}
u32 cellGcmSetUserHandler(u32 handler)
void cellGcmSetUserHandler(u32 handler_addr)
{
cellGcmSys->Warning("cellGcmSetUserHandler(handler=0x%x)", handler);
return handler;
cellGcmSys->Warning("cellGcmSetUserHandler(handler_addr=0x%x)", handler_addr);
if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr))
{
cellGcmSys->Error("cellGcmSetUserHandler(handler_addr=%d): invalid address", handler_addr);
}
Emu.GetGSManager().GetRender().m_user_handler.SetAddr(handler_addr);
}
int cellGcmSetVBlankHandler()
void cellGcmSetVBlankHandler(u32 handler_addr)
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
cellGcmSys->Warning("cellGcmSetVBlankHandler(handler_addr=0x%x)", handler_addr);
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)
@ -699,10 +709,11 @@ int cellGcmGetDisplayBufferByFlipIndex()
return CELL_OK;
}
int cellGcmgetLastFlipTime()
u64 cellGcmGetLastFlipTime()
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
cellGcmSys->Log("cellGcmGetLastFlipTime()");
return Emu.GetGSManager().GetRender().m_last_flip_time;
}
int cellGcmGetLastSecondVTime()
@ -711,10 +722,11 @@ int cellGcmGetLastSecondVTime()
return CELL_OK;
}
int cellGcmGetVBlankCount()
u64 cellGcmGetVBlankCount()
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
cellGcmSys->Log("cellGcmGetVBlankCount()");
return Emu.GetGSManager().GetRender().m_vblank_count;
}
int cellGcmInitSystemMode()
@ -1156,7 +1168,7 @@ void cellGcmSys_init()
cellGcmSys->AddFunc(0xe315a0b2, cellGcmGetConfiguration);
cellGcmSys->AddFunc(0x371674cf, cellGcmGetDisplayBufferByFlipIndex);
cellGcmSys->AddFunc(0x72a577ce, cellGcmGetFlipStatus);
cellGcmSys->AddFunc(0x63387071, cellGcmgetLastFlipTime);
cellGcmSys->AddFunc(0x63387071, cellGcmGetLastFlipTime);
cellGcmSys->AddFunc(0x23ae55a3, cellGcmGetLastSecondVTime);
cellGcmSys->AddFunc(0x055bd74d, cellGcmGetTiledPitchSize);
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;
}
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)
{
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())
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;
if(!cellPngDec->CheckId(subHandle, subHandle_data))
return CELL_PNGDEC_ERROR_FATAL;
@ -167,6 +184,14 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellPngDecInfo
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)
{
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;
}
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)
{
if (!inParam.IsGood() || !outParam.IsGood())
@ -333,6 +369,15 @@ int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, const mem_ptr_t<CellPn
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()
{
cellPngDec->AddFunc(0x157d30c5, cellPngDecCreate);
@ -343,11 +388,12 @@ void cellPngDec_init()
cellPngDec->AddFunc(0x2310f155, cellPngDecDecodeData);
cellPngDec->AddFunc(0xe97c9bd4, cellPngDecSetParameter);
/*cellPngDec->AddFunc(0x48436b2d, cellPngDecExtCreate);
cellPngDec->AddFunc(0x0c515302, cellPngDecExtOpen);
cellPngDec->AddFunc(0x8b33f863, cellPngDecExtReadHeader);
cellPngDec->AddFunc(0x726fc1d0, cellPngDecExtDecodeData);
cellPngDec->AddFunc(0x9e9d7d42, cellPngDecExtSetParameter);
/*cellPngDec->AddFunc(0x48436b2d, cellPngDecExtCreate);
cellPngDec->AddFunc(0x7585a275, cellPngDecGetbKGD);
cellPngDec->AddFunc(0x7a062d26, cellPngDecGetcHRM);
cellPngDec->AddFunc(0xb153629c, cellPngDecGetgAMA);

View file

@ -124,3 +124,54 @@ struct CellPngDecMainHandle
be_t<u32> threadInParam;
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 int cellGcmSetFlipMode(u32 mode);
extern int cellGcmSetFlipHandler(u32 handler_addr);
extern s32 cellGcmAddressToOffset(u64 address, mem32_t offset);
extern void cellGcmSetFlipHandler(u32 handler_addr);
extern int cellGcmAddressToOffset(u64 address, mem32_t offset);
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 cellGcmSetSecondVFrequency(u32 freq);
extern u32 cellGcmGetLabelAddress(u8 index);
extern u32 cellGcmSetVBlankHandler(u32 handler);
extern void cellGcmSetVBlankHandler(u32 handler);
extern u32 cellGcmSetSecondVHandler(u32 handler);
extern u32 cellGcmGetTiledPitchSize(u32 size);
@ -1096,19 +1096,16 @@ int cellRescSetBufferAddress(mem32_t colorBuffers, mem32_t vertexArray, mem32_t
return CELL_OK;
}
int cellRescSetFlipHandler(u32 handler_addr)
void cellRescSetFlipHandler(u32 handler_addr)
{
cellResc->Warning("cellRescSetFlipHandler(handler_addr=0x%x)", handler_addr);
if (handler_addr != 0 && !Memory.IsGoodAddr(handler_addr))
{
cellResc->Error("cellRescSetFlipHandler : CELL_EFAULT");
return CELL_EFAULT;
cellResc->Error("cellRescSetFlipHandler(handler_addr=%d): invalid address", handler_addr);
}
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr);
return CELL_OK;
}
void cellRescResetFlipStatus()
@ -1131,10 +1128,11 @@ int cellRescGetRegisterCount()
return CELL_OK;
}
int cellRescGetLastFlipTime()
u64 cellRescGetLastFlipTime()
{
UNIMPLEMENTED_FUNC(cellResc);
return CELL_OK;
cellResc->Log("cellRescGetLastFlipTime()");
return Emu.GetGSManager().GetRender().m_last_flip_time;
}
int cellRescSetRegisterCount()
@ -1143,10 +1141,16 @@ int cellRescSetRegisterCount()
return CELL_OK;
}
int cellRescSetVBlankHandler()
void cellRescSetVBlankHandler(u32 handler_addr)
{
UNIMPLEMENTED_FUNC(cellResc);
return CELL_OK;
cellResc->Warning("cellRescSetVBlankHandler(handler_addr=0x%x)", handler_addr);
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)

View file

@ -10,6 +10,7 @@
#include "cellSysutil.h"
#include "cellSysutil_SaveData.h"
#include "cellGame.h"
#include "Loader/PSF.h"
@ -380,8 +381,11 @@ int cellSysutilUnregisterCallback(int slot)
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;
if(type & CELL_MSGDIALOG_DIALOG_TYPE_NORMAL)
@ -402,7 +406,7 @@ int cellMsgDialogOpen2(u32 type, char* msgString, mem_func_ptr_t<CellMsgDialogCa
style |= rOK;
}
int res = rMessageBox(std::string(msgString), rGetApp().GetAppName(), style);
int res = rMessageBox(std::string(msgString.GetString()), rGetApp().GetAppName(), style);
u64 status;
@ -919,22 +923,24 @@ int cellHddGameCheck(u32 version, u32 dirName_addr, u32 errDialog, mem_func_ptr_
return CELL_OK;
}
bool bgm_playback_enabled = false;
bool bgm_playback_enabled = true;
int cellSysutilEnableBgmPlayback()
{
cellSysutil->Warning("cellSysutilEnableBgmPlayback()");
// TODO
bgm_playback_enabled = true;
return CELL_OK;
}
int cellSysutilEnableBgmPlaybackEx()
int cellSysutilEnableBgmPlaybackEx(mem_ptr_t<CellSysutilBgmPlaybackExtraParam> param)
{
cellSysutil->Warning("cellSysutilEnableBgmPlaybackEx()");
cellSysutil->Warning("cellSysutilEnableBgmPlaybackEx(param_addr=0x%x)", param.GetAddr());
bgm_playback_enabled = true;
// TODO
bgm_playback_enabled = true;
return CELL_OK;
}
@ -943,42 +949,43 @@ int cellSysutilDisableBgmPlayback()
{
cellSysutil->Warning("cellSysutilDisableBgmPlayback()");
// TODO
bgm_playback_enabled = false;
return CELL_OK;
}
int cellSysutilDisableBgmPlaybackEx()
int cellSysutilDisableBgmPlaybackEx(mem_ptr_t<CellSysutilBgmPlaybackExtraParam> param)
{
cellSysutil->Warning("cellSysutilDisableBgmPlaybackEx()");
bgm_playback_enabled = false;
return CELL_OK;
}
int cellSysutilGetBgmPlaybackStatus(mem_ptr_t<CellBgmPlaybackStatus> status)
{
cellSysutil->Warning("cellSysutilGetBgmPlaybackStatus(status=0x%x)", status.GetAddr());
cellSysutil->Warning("cellSysutilDisableBgmPlaybackEx(param_addr=0x%x)", param.GetAddr());
// TODO
status->playbackState = CELL_BGMPLAYBACK_STATUS_STOP;
status->enabled = bgm_playback_enabled ? CELL_BGMPLAYBACK_STATUS_ENABLE : CELL_BGMPLAYBACK_STATUS_DISABLE;
status->fadeRatio = 0; // volume ratio
bgm_playback_enabled = false;
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->reserved, 0, sizeof(status->reserved));
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
status2->playbackState = CELL_BGMPLAYBACK_STATUS_STOP;
status2->enabled = bgm_playback_enabled ? CELL_BGMPLAYBACK_STATUS_ENABLE : CELL_BGMPLAYBACK_STATUS_DISABLE;
status2->fadeRatio = 0; // volume ratio
memset(status2->contentId, 0, sizeof(status2->contentId));
status2->playerState = CELL_SYSUTIL_BGMPLAYBACK_STATUS_STOP;
memset(status2->reserved, 0, sizeof(status2->reserved));
return CELL_OK;
}
@ -991,6 +998,12 @@ int cellWebBrowserEstimate2(mem8_ptr_t _config, mem32_ptr_t memSize)
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()
{
cellSysutil->AddFunc(0x40e895d3, cellSysutilGetSystemParamInt);
@ -1068,4 +1081,7 @@ void cellSysutil_init()
//cellSysutil->AddFunc(0xe7fa820b, cellSaveDataEnableOverlay);
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:
if (vdec.reader.size < (u32)buf_size /*&& !vdec.just_started*/)
{
while (vdec.job.IsEmpty())
while (!vdec.job.GetCountUnsafe())
{
if (Emu.IsStopped())
{
@ -44,6 +44,7 @@ next:
switch (vdec.job.Peek().type)
{
case vdecEndSeq:
case vdecClose:
{
buf_size = vdec.reader.size;
}
@ -147,7 +148,7 @@ u32 vdecOpen(VideoDecoder* data)
break;
}
if (vdec.job.IsEmpty() && vdec.is_running)
if (!vdec.job.GetCountUnsafe() && vdec.is_running)
{
Sleep(1);
continue;
@ -189,10 +190,8 @@ u32 vdecOpen(VideoDecoder* data)
cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
cb.Branch(true); // ???*/
avcodec_close(vdec.ctx);
avformat_close_input(&vdec.fmt);
vdec.is_running = false;
vdec.just_finished = true;
}
break;
@ -244,7 +243,13 @@ u32 vdecOpen(VideoDecoder* data)
} 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);
if (err)
@ -285,7 +290,7 @@ u32 vdecOpen(VideoDecoder* data)
av_dict_set(&opts, "refcounted_frames", "1", 0);
{
std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
// not multithread-safe
// not multithread-safe (???)
err = avcodec_open2(vdec.ctx, codec, &opts);
}
if (err)
@ -294,8 +299,6 @@ u32 vdecOpen(VideoDecoder* data)
Emu.Pause();
break;
}
//vdec.ctx->flags |= CODEC_FLAG_TRUNCATED;
//vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS;
vdec.just_started = false;
}
@ -303,8 +306,9 @@ u32 vdecOpen(VideoDecoder* data)
while (true)
{
if (Emu.IsStopped())
if (Emu.IsStopped() || vdec.job.PeekIfExist().type == vdecClose)
{
vdec.is_finished = true;
LOG_WARNING(HLE, "vdecDecodeAu: aborted");
return;
}
@ -498,7 +502,7 @@ int cellVdecClose(u32 handle)
vdec->job.Push(VdecTask(vdecClose));
while (!vdec->is_finished || !vdec->frames.IsEmpty())
while (!vdec->is_finished)
{
if (Emu.IsStopped())
{
@ -674,14 +678,14 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr)
return CELL_VDEC_ERROR_FATAL;
}
VdecFrame& vf = vdec->frames.Peek();
if (vdec->frames.IsEmpty())
{
Sleep(1);
Sleep(1); // hack
return CELL_VDEC_ERROR_EMPTY;
}
VdecFrame& vf = vdec->frames.Peek();
AVFrame& frame = *vf.data;
mem_ptr_t<CellVdecPicItem> info(vdec->memAddr + vdec->memBias);

View file

@ -647,6 +647,7 @@ struct CellVdecMpeg2Info
enum VdecJobType : u32
{
vdecInvalid,
vdecStartSeq,
vdecEndSeq,
vdecDecodeAu,
@ -675,6 +676,7 @@ struct VdecTask
}
VdecTask()
: type(vdecInvalid)
{
}
};
@ -697,6 +699,7 @@ public:
volatile bool is_running;
volatile bool is_finished;
bool just_started;
bool just_finished;
AVCodecContext* ctx;
AVFormatContext* fmt;
@ -735,6 +738,7 @@ public:
, is_finished(false)
, is_running(false)
, just_started(false)
, just_finished(false)
, ctx(nullptr)
, vdecCb(nullptr)
{
@ -764,6 +768,7 @@ public:
~VideoDecoder()
{
// TODO: check finalization
if (ctx)
{
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);
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;
u8 k_licensee[0x10];
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)
{
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);
if (!fd.IsGood() || (!arg.IsGood() && size))
/*if (!fd.IsGood() || (!arg.IsGood() && size))
return CELL_EFAULT;
if (flags != CELL_O_RDONLY)
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")
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);
return CELL_OK;
return CELL_OK;*/
return cellFsOpen(path_addr, flags, fd, arg, size);
}
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);
ef->signal.unlock(tid);
u64 flags = ef->flags;
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;
}
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())
{
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;
}

View file

@ -116,6 +116,12 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
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);
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);
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;
}

View file

@ -11,6 +11,7 @@
#include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/PPUInstrTable.h"
#include "Emu/FS/vfsFile.h"
#include "Emu/FS/vfsDeviceLocalFile.h"
#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());
}
// 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
if(m_elf_path.empty())

View file

@ -88,7 +88,7 @@ struct wxWriter : Log::LogListener
default:
break;
}
llogcon->AppendText(wxString(msg.mText));
llogcon->AppendText(fmt::FromUTF8(msg.mText));
}
}
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\cellDmux.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\cellJpgDec.h" />
<ClInclude Include="Emu\SysCalls\Modules\cellPamf.h" />

View file

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