diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index b09d78954b..88fa4ae462 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -74,8 +74,9 @@ static func_caller* sc_table[1024] = bind_func(sys_cond_wait), //107 (0x06B) bind_func(sys_cond_signal), //108 (0x06C) bind_func(sys_cond_signal_all), //109 (0x06D) - null_func, null_func, null_func, null_func, null_func, //114 - null_func, null_func, null_func, null_func, null_func, //119 + null_func, null_func, null_func, null_func, //110 (0x06E) + bind_func(sys_semaphore_get_value), //114 (0x072) + null_func, null_func, null_func, null_func, null_func, //119 (0x077) bind_func(sys_rwlock_create), //120 (0x078) bind_func(sys_rwlock_destroy), //121 (0x079) bind_func(sys_rwlock_rlock), //122 (0x07A) diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 03a2b6a815..20c54bb211 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -134,6 +134,7 @@ extern int sys_semaphore_destroy(u32 sem); extern int sys_semaphore_wait(u32 sem, u64 timeout); extern int sys_semaphore_trywait(u32 sem); extern int sys_semaphore_post(u32 sem, int count); +extern int sys_semaphore_get_value(u32 sem, u32 count_addr); //sys_lwmutex extern int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp index 8b11792c2a..bc05e4612e 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp @@ -17,6 +17,7 @@ struct semaphore { wxSemaphore sem; semaphore_attr attr; + int sem_count; semaphore(int initial_count, int max_count, semaphore_attr attr) : sem(initial_count, max_count) @@ -90,7 +91,23 @@ int sys_semaphore_post(u32 sem, int count) semaphore* sem_data = nullptr; if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH; - while(count--) sem_data->sem.Post(); + while(count--) + { + sem_data->sem_count++; // Increment internal counter for sys_semaphore_get_value. + sem_data->sem.Post(); + } + + return CELL_OK; +} + +int sys_semaphore_get_value(u32 sem, u32 count_addr) +{ + sys_sem.Log("sys_semaphore_get_value(sem=0x%x, count_addr=0x%x)", sem, count_addr); + + semaphore* sem_data = nullptr; + if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH; + + Memory.Write32(count_addr, sem_data->sem_count); return CELL_OK; } diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index ea0239c1c0..bd5797a585 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -188,8 +188,55 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event)) wxString fileIn = ctrl.GetPath()+elf[i]; wxString fileOut = (ctrl.GetPath()+elf[i])+".elf"; - scetool_decrypt((scetool::s8 *)fileIn.mb_str(), (scetool::s8 *)fileOut.mb_str()); + // Check if the data really needs to be decrypted. + FILE *f; + if((f = fopen(fileIn.mb_str(), "rb")) == NULL) + { + ConLog.Error("Could not open game boot file!"); + return; + } + + // Get the key version. + fseek(f, 0x08, SEEK_SET); + s16 key_version; + fread(&key_version, 1, sizeof(key_version), f); + be_t key_version_be; + key_version_be.FromLE(key_version); + + // Get the real elf offset. + fseek(f, 0x10, SEEK_SET); + s64 elf_offset; + fread(&elf_offset, 1, sizeof(elf_offset), f); + be_t elf_offset_be; + elf_offset_be.FromLE(elf_offset); + + fclose(f); + + if(key_version_be.ToBE() == 0x8000) + { + ConLog.Warning("Debug SELF detected! Removing fake header..."); + FILE *in; + FILE *out; + in = fopen(fileIn, "rb"); + out = fopen(fileOut, "wb"); + + // Start at the real elf offset. + fseek(in, elf_offset_be.ToBE(), SEEK_SET); + + // Copy the data. + int c; + while ((c = fgetc(in)) != EOF) + fputc(c, out); + + fclose(out); + fclose(in); + } + else + { + scetool_decrypt((scetool::s8 *)fileIn.mb_str(), (scetool::s8 *)fileOut.mb_str()); + } + Emu.SetPath((ctrl.GetPath()+elf[i])+".elf"); Emu.Load(); if (!wxRemoveFile((ctrl.GetPath()+elf[i])+".elf")) @@ -292,11 +339,57 @@ void MainFrame::BootSelf(wxCommandEvent& WXUNUSED(event)) wxString fileIn = ctrl.GetPath(); wxString fileOut = ctrl.GetPath()+".elf"; - if (!scetool_decrypt((scetool::s8 *)fileIn.mb_str(), (scetool::s8 *)fileOut.mb_str())) + // Check if the data really needs to be decrypted. + FILE *f; + if((f = fopen(fileIn.mb_str(), "rb")) == NULL) { - ConLog.Write("SELF: Could not decrypt file"); + ConLog.Error("Could not open SELF file!"); return; } + + // Get the key version. + fseek(f, 0x08, SEEK_SET); + s16 key_version; + fread(&key_version, 1, sizeof(key_version), f); + be_t key_version_be; + key_version_be.FromLE(key_version); + + // Get the real elf offset. + fseek(f, 0x10, SEEK_SET); + s64 elf_offset; + fread(&elf_offset, 1, sizeof(elf_offset), f); + be_t elf_offset_be; + elf_offset_be.FromLE(elf_offset); + + fclose(f); + + if(key_version_be.ToBE() == 0x8000) + { + ConLog.Warning("Debug SELF detected! Removing fake header..."); + FILE *in; + FILE *out; + in = fopen(fileIn, "rb"); + out = fopen(fileOut, "wb"); + + // Start at the real elf offset. + fseek(in, elf_offset_be.ToBE(), SEEK_SET); + + // Copy the data. + int c; + while ((c = fgetc(in)) != EOF) + fputc(c, out); + + fclose(out); + fclose(in); + } + else + { + if (!scetool_decrypt((scetool::s8 *)fileIn.mb_str(), (scetool::s8 *)fileOut.mb_str())) + { + ConLog.Write("SELF: Could not decrypt file"); + return; + } + } Emu.SetPath(ctrl.GetPath()+".elf"); Emu.Load();