diff --git a/Utilities/GNU.h b/Utilities/GNU.h index a3a2ba48e5..a79dfbf3d0 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -6,6 +6,14 @@ #define thread_local __thread #endif +template +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 #include diff --git a/Utilities/SQueue.h b/Utilities/SQueue.h index 4e3b317a9d..9aa7e58356 100644 --- a/Utilities/SQueue.h +++ b/Utilities/SQueue.h @@ -4,8 +4,6 @@ template 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 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 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 lock(m_mutex); + return m_count; + } + + u32 GetCountUnsafe() { return m_count; } - volatile bool IsEmpty() // may be thread unsafe + bool IsEmpty() { + std::lock_guard lock(m_mutex); return !m_count; } void Clear() { std::lock_guard 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 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 lock(m_mutex); + if (m_count <= pos) + { + return def_value; + } + else + { + return m_data[(m_pos + pos) % SQSize]; + } + } }; diff --git a/rpcs3/Emu/Audio/sysutil_audio.h b/rpcs3/Emu/Audio/sysutil_audio.h index 94ea6dafd0..2fd567461f 100644 --- a/rpcs3/Emu/Audio/sysutil_audio.h +++ b/rpcs3/Emu/Audio/sysutil_audio.h @@ -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 systemBgmFadeInTime; + be_t systemBgmFadeOutTime; + be_t gameBgmFadeInTime; + be_t gameBgmFadeOutTime; + char reserved[8]; +}; diff --git a/rpcs3/Emu/FS/vfsLocalFile.cpp b/rpcs3/Emu/FS/vfsLocalFile.cpp index 7eceb1e8d6..7a6e71c09c 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.cpp +++ b/rpcs3/Emu/FS/vfsLocalFile.cpp @@ -115,3 +115,8 @@ bool vfsLocalFile::IsOpened() const { return m_file.IsOpened() && vfsFileBase::IsOpened(); } + +bool vfsLocalFile::Exists(const std::string& path) +{ + return rFileExists(path); +} \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsLocalFile.h b/rpcs3/Emu/FS/vfsLocalFile.h index a7aac7b1ea..c61dd495e7 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.h +++ b/rpcs3/Emu/FS/vfsLocalFile.h @@ -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; diff --git a/rpcs3/Emu/GS/GCM.h b/rpcs3/Emu/GS/GCM.h index 8a30680a88..8d60241d93 100644 --- a/rpcs3/Emu/GS/GCM.h +++ b/rpcs3/Emu/GS/GCM.h @@ -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) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 97344c35d4..17aed8412a 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -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"); diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index 287b754d9a..1a99f22f8e 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -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(); diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 5bb3058df1..6fb367dc4f 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -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 diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index aa72d95f64..fec90b45d1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -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 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 pcm(adec->memAddr + adec->memBias); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 88a6e6bf47..108844f22c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -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--) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index ee799261b7..3bde3766ac 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -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 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 esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); @@ -242,6 +237,7 @@ u32 dmuxOpen(Demuxer* data) if (es.isfull()) { stream = backup; + Sleep(1); continue; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 02af4d083c..1d0dfef4e9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -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 hddFreeSizeKB; - be_t sizeKB; - be_t sysSizeKB; -}; +std::string contentInfo = ""; +std::string usrdir = ""; int cellGameBootCheck(mem32_t type, mem32_t attributes, mem_ptr_t size, mem_list_ptr_t 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 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 dirName, mem_ptr_t 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 contentInfoPath, mem_list_ptr_t usrdirPath) +int cellGameContentPermit(mem_list_ptr_t contentInfoPath, mem_list_ptr_t 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 dirName, u32 errDialog, + mem_func_ptr_t cbResult, mem_ptr_t get, mem_ptr_t 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 cbResult; + MemoryAllocator cbGet; + MemoryAllocator 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 dirName, u32 errDialog, + mem_func_ptr_t cbResult, mem_ptr_t get, mem_ptr_t 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 init, mem_list_ptr_t tmp_contentInfoPath, mem_list_ptr_t 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)) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.h b/rpcs3/Emu/SysCalls/Modules/cellGame.h new file mode 100644 index 0000000000..12a0165eba --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.h @@ -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 hddFreeSizeKB; + be_t sizeKB; + be_t 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 result; + be_t errNeedSizeKB; + be_t invalidMsg_addr; + be_t 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 parentalLevel; + be_t attribute; + char reserved2[256]; +}; + +struct CellGameDataStatGet +{ + be_t hddFreeSizeKB; + be_t isNewData; + char contentInfoPath[CELL_GAMEDATA_PATH_MAX]; + char gameDataPath[CELL_GAMEDATA_PATH_MAX]; + char reserved0[2]; + be_t st_atime_; + be_t st_mtime_; + be_t st_ctime_; + CellGameDataSystemFileParam getParam; + be_t sizeKB; + be_t sysSizeKB; + char reserved1[68]; +}; + +struct CellGameDataStatSet +{ + mem_beptr_t setParam; + be_t reserved; +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 2133bac53f..f91232d0c4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -421,18 +421,16 @@ int cellGcmSetFlip(mem_ptr_t 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 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); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 4ffcc7d04f..5f61fb8aa1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -93,6 +93,23 @@ int cellPngDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t s return CELL_OK; } +int cellPngDecExtOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t src, u32 openInfo, mem_ptr_t cbCtrlStrm, mem_ptr_t 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 streamInfo; + MemoryAllocator 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_tWarning("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 info, mem_ptr_t 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 dataCtrlParam, mem_ptr_t 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 dataCtrlParam, + mem_ptr_t dataOutInfo, mem_ptr_t cbCtrlDisp, mem_ptr_t 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 inParam, mem_ptr_t outParam) { if (!inParam.IsGood() || !outParam.IsGood()) @@ -333,6 +369,15 @@ int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, const mem_ptr_t inParam, mem_ptr_t outParam, + mem_ptr_t extInParam, mem_ptr_t 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); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h index 9d48c68b01..b93f82ba8e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h @@ -124,3 +124,54 @@ struct CellPngDecMainHandle be_t threadInParam; be_t threadOutParam; }; + +struct CellPngDecStrmInfo +{ + be_t decodedStrmSize; +}; + +struct CellPngDecStrmParam +{ + be_t strmPtr; + be_t strmSize; +}; + +struct CellPngDecCbCtrlStrm +{ + mem_func_beptr_t strmInfo, mem_ptr_t strmParam, u32 cbCtrlStrmArg)> cbCtrlStrmFunc; + be_t cbCtrlStrmArg; +}; + +struct CellPngDecCbCtrlDisp +{ + be_t cbCtrlDispFunc_addr; + be_t cbCtrlDispArg; +}; + +struct CellPngDecDispParam +{ + be_t nextOutputImage_addr; +}; + +struct CellPngDecExtInfo +{ + be_t reserved; +}; + +struct CellPngDecExtInParam +{ + be_t bufferMode; // CellPngDecBufferMode + be_t outputCounts; + be_t spuMode; // CellPngDecSpuMode +}; + +struct CellPngDecExtOutParam +{ + be_t outputWidthByte; + be_t outputHeight; +}; + +struct CellPngDecOpnParam +{ + be_t selectChunk; +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp index dc69a23dfa..e50e98abab 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp @@ -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 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) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index ebad56ef57..b8bf9ec0a2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -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 callback, mem_ptr_t userData, u32 extParam) +int cellMsgDialogOpen2(u32 type, mem_list_ptr_t msgString, mem_func_ptr_t callback, mem_ptr_t 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_tWarning("cellSysutilEnableBgmPlayback()"); + // TODO bgm_playback_enabled = true; return CELL_OK; } -int cellSysutilEnableBgmPlaybackEx() +int cellSysutilEnableBgmPlaybackEx(mem_ptr_t 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 param) { - cellSysutil->Warning("cellSysutilDisableBgmPlaybackEx()"); - - bgm_playback_enabled = false; - - return CELL_OK; -} - -int cellSysutilGetBgmPlaybackStatus(mem_ptr_t 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 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 status2) +int cellSysutilGetBgmPlaybackStatus2(mem_ptr_t 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 dirName, u32 errDialog, + mem_func_ptr_t cbResult, mem_ptr_t get, mem_ptr_t set)> funcStat, u32 container); + +extern int cellGameDataCheckCreate(u32 version, const mem_list_ptr_t dirName, u32 errDialog, + mem_func_ptr_t cbResult, mem_ptr_t get, mem_ptr_t 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); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 29b12f10f7..d76d846c4d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -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 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 info(vdec->memAddr + vdec->memBias); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index 7c9508d049..5b6a5633d2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -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--) diff --git a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp index aaff7e08b1..20dc321c69 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp @@ -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++) diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 1d35191bd7..63de40521f 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -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 g_FsAioReadID( 0 ); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp index 622e333ece..743c37beb9 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp @@ -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; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index 6e8a6c4e01..15fe4a6d86 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -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; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 6c3d3667f1..857b172e86 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -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()) diff --git a/rpcs3/Gui/ConLogFrame.cpp b/rpcs3/Gui/ConLogFrame.cpp index 3e5a7056a8..be7f4fc6ef 100644 --- a/rpcs3/Gui/ConLogFrame.cpp +++ b/rpcs3/Gui/ConLogFrame.cpp @@ -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) diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 02e2f292b5..fb34b8f476 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -339,6 +339,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 03b8528f49..cc85fc9f6c 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1072,5 +1072,8 @@ Utilities + + Emu\SysCalls\Modules + \ No newline at end of file