Merge refactoring branch & Krofna's pull req. #46

This commit is contained in:
Alexandro Sánchez Bach 2014-02-23 02:39:46 +01:00
commit 696e00a570
32 changed files with 492 additions and 894 deletions

View File

@ -10,4 +10,5 @@
#define Sleep(x) usleep(x * 1000)
#define mkdir(x) mkdir(x, 0777)
#define INFINITE 0xFFFFFFFF
#define _CRT_ALIGN(x) __attribute__((aligned(x)))
#endif

View File

@ -104,14 +104,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scetool", "scetool", "{AB33
scetool\zlib.h = scetool\zlib.h
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unpkg", "unpkg", "{9F2D2094-BA46-4456-8C45-FD9EC108F1EE}"
ProjectSection(SolutionItems) = preProject
unpkg\oddkeys.h = unpkg\oddkeys.h
unpkg\ps3_common.h = unpkg\ps3_common.h
unpkg\unpkg.c = unpkg\unpkg.c
unpkg\unpkg.h = unpkg\unpkg.h
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ribbon", "wxWidgets\build\msw\wx_vc10_ribbon.vcxproj", "{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stc", "wxWidgets\build\msw\wx_vc10_stc.vcxproj", "{23E1C437-A951-5943-8639-A17F3CF2E606}"

View File

@ -11,7 +11,12 @@ if (CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-fpermissive) # TODO: remove me
endif()
find_package(wxWidgets)
add_definitions(-DGL_GLEXT_PROTOTYPES)
add_definitions(-DGLX_GLXEXT_PROTOTYPES)
find_package(wxWidgets COMPONENTS core base net aui gl REQUIRED)
find_package(OpenGL REQUIRED)
find_package(ZLIB REQUIRED)
include("${wxWidgets_USE_FILE}")
@ -27,11 +32,15 @@ ${CMAKE_SOURCE_DIR}/..
file(
GLOB_RECURSE
RPCS3_SRC
${CMAKE_SOURCE_DIR}/rpcs3.cpp
${CMAKE_SOURCE_DIR}/AppConnector.cpp
${CMAKE_SOURCE_DIR}/Ini.cpp
${CMAKE_SOURCE_DIR}/Emu/*
${CMAKE_SOURCE_DIR}/Gui/*
${CMAKE_SOURCE_DIR}/Loader/*
${CMAKE_SOURCE_DIR}/../Utilities/*
${CMAKE_SOURCE_DIR}/../scetool/scetool.cpp
)
add_executable(rpcs3 ${RPCS3_SRC})
target_link_libraries(rpcs3 ${wxWidgets_LIBRARIES})
target_link_libraries(rpcs3 ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${ZLIB_LIBRARIES})

View File

@ -158,7 +158,7 @@ struct DMAC
u32 queue_pos;
u32 proxy_pos;
long queue_lock;
long proxy_lock;
volatile std::atomic<int> proxy_lock;
bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
@ -193,7 +193,7 @@ struct DMAC
return MFC_PPU_DMA_QUEUE_FULL;
}
/* while (_InterlockedExchange(&proxy_lock, 1));
/* while (std::atomic_exchange(&proxy_lock, 1));
_mm_lfence();
DMAC_Proxy& p = proxy[proxy_pos];
p.cmd = cmd;
@ -212,7 +212,7 @@ struct DMAC
void ClearCmd()
{
while (_InterlockedExchange(&proxy_lock, 1));
while (std::atomic_exchange(&proxy_lock, 1));
_mm_lfence();
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
_mm_sfence();
@ -298,4 +298,4 @@ struct MFC
MFC_QStatus.SetValue(mask);
}
}
};
};

View File

@ -647,7 +647,12 @@ void GLGSRender::OnInitThread()
glEnable(GL_TEXTURE_2D);
glEnable(GL_SCISSOR_TEST);
#ifdef _WIN32
glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0);
#else
if (GLXDrawable drawable = glXGetCurrentDrawable())
glXSwapIntervalEXT(glXGetCurrentDisplay(), drawable, Ini.GSVSyncEnable.GetValue() ? 1 : 0);
#endif
glGenTextures(1, &g_depth_tex);
glGenTextures(1, &g_flip_tex);
@ -964,7 +969,7 @@ void GLGSRender::ExecCMD()
if(m_set_depth_bounds)
{
//ConLog.Warning("glDepthBounds(%f, %f)", m_depth_bounds_min, m_depth_bounds_max);
glDepthBounds(m_depth_bounds_min, m_depth_bounds_max);
glDepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max);
checkForGlError("glDepthBounds");
}

View File

@ -175,10 +175,10 @@ public:
default: ConLog.Error("Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, is_swizzled ? "swizzled" : "linear", tex.GetFormat() & 0x40); break;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.Getmipmap() - 1);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.Getmipmap() > 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.GetMipmap() - 1);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.GetMipmap() > 1);
if(format != 0x81 && format != 0x94)
if(format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16)
{
u8 remap_a = tex.GetRemap() & 0x3;
u8 remap_r = (tex.GetRemap() >> 2) & 0x3;
@ -245,7 +245,7 @@ public:
//Unbind();
if(is_swizzled && format == 0x85)
if(is_swizzled && format == CELL_GCM_TEXTURE_A8R8G8B8)
{
free(unswizzledPixels);
}

View File

@ -78,7 +78,7 @@ OPENGL_PROC(PFNGLPROGRAMUNIFORM1FPROC, ProgramUniform1f);
OPENGL_PROC(PFNGLPROGRAMUNIFORM4FPROC, ProgramUniform4f);
OPENGL_PROC(PFNGLUNIFORMMATRIX4FVPROC, UniformMatrix4fv);
OPENGL_PROC(PFNGLUSEPROGRAMPROC, UseProgram);
OPENGL_PROC2(PFNGLDEPTHBOUNDSEXTPROC, DepthBounds, glDepthBoundsEXT);
OPENGL_PROC2(PFNGLDEPTHBOUNDSEXTPROC, DepthBoundsEXT, glDepthBoundsEXT);
OPENGL_PROC(PFNGLSTENCILOPSEPARATEPROC, StencilOpSeparate);
OPENGL_PROC(PFNGLSTENCILFUNCSEPARATEPROC, StencilFuncSeparate);
OPENGL_PROC(PFNGLSTENCILMASKSEPARATEPROC, StencilMaskSeparate);

View File

@ -3,18 +3,22 @@
void InitProcTable()
{
#ifdef _WIN32
#define OPENGL_PROC(p, n) OPENGL_PROC2(p, n, gl##n)
#define OPENGL_PROC2(p, n, tn) /*if(!gl##n)*/ if(!(gl##n = (p)wglGetProcAddress(#tn))) ConLog.Error("OpenGL: initialization of " #tn " failed.")
#include "GLProcTable.tbl"
#undef OPENGL_PROC
#undef OPENGL_PROC2
#endif
}
#ifdef _WIN32
#define OPENGL_PROC(p, n) p gl##n = nullptr
#define OPENGL_PROC2(p, n, tn) OPENGL_PROC(p, n)
#include "GLProcTable.tbl"
#undef OPENGL_PROC
#undef OPENGL_PROC2
#endif
OpenGL::OpenGL()
{
@ -29,18 +33,22 @@ OpenGL::~OpenGL()
void OpenGL::Init()
{
#ifdef _WIN32
#define OPENGL_PROC(p, n) OPENGL_PROC2(p, n, gl##n)
#define OPENGL_PROC2(p, n, tn) if(!(n = (p)wglGetProcAddress(#tn))) ConLog.Error("OpenGL: initialization of " #tn " failed.")
#include "GLProcTable.tbl"
#undef OPENGL_PROC
#undef OPENGL_PROC2
#endif
}
void OpenGL::Close()
{
#ifdef _WIN32
#define OPENGL_PROC(p, n) n = nullptr
#define OPENGL_PROC2(p, n, tn) OPENGL_PROC(p, n)
#include "GLProcTable.tbl"
#undef OPENGL_PROC
#undef OPENGL_PROC2
#endif
}

View File

@ -4,7 +4,6 @@
#ifdef _WIN32
typedef BOOL (WINAPI* PFNWGLSWAPINTERVALEXTPROC) (int interval);
#endif
#define OPENGL_PROC(p, n) extern p gl##n
#define OPENGL_PROC2(p, n, tn) OPENGL_PROC(p, n)
@ -12,6 +11,11 @@ typedef BOOL (WINAPI* PFNWGLSWAPINTERVALEXTPROC) (int interval);
#undef OPENGL_PROC
#undef OPENGL_PROC2
#else
#include <GL/glx.h>
#include <GL/glxext.h>
#endif
void InitProcTable();
struct OpenGL

View File

@ -1,5 +1,5 @@
#include "stdafx.h"
#include "RSXThread.h"
#include "RSXTexture.h"
RSXTexture::RSXTexture()
{
@ -70,7 +70,7 @@ u8 RSXTexture::GetFormat() const
return ((methodRegisters[NV4097_SET_TEXTURE_FORMAT + (m_index*32)] >> 8) & 0xff);
}
u16 RSXTexture::Getmipmap() const
u16 RSXTexture::GetMipmap() const
{
return ((methodRegisters[NV4097_SET_TEXTURE_FORMAT + (m_index*32)] >> 16) & 0xffff);
}
@ -199,4 +199,4 @@ void RSXTexture::SetControl3(u16 depth, u32 pitch)
{
m_depth = depth;
m_pitch = pitch;
}
}

62
rpcs3/Emu/GS/RSXTexture.h Normal file
View File

@ -0,0 +1,62 @@
#pragma once
class RSXTexture
{
u8 m_index;
public:
u32 m_pitch;
u16 m_depth;
public:
RSXTexture();
RSXTexture(u8 index);
void Init();
// Offset
u32 GetOffset() const;
// Format
u8 GetLocation() const;
bool isCubemap() const;
u8 GetBorderType() const;
u8 GetDimension() const;
u8 GetFormat() const;
u16 GetMipmap() const;
// Address
u8 GetWrapS() const;
u8 GetWrapT() const;
u8 GetWrapR() const;
u8 GetUnsignedRemap() const;
u8 GetZfunc() const;
u8 GetGamma() const;
u8 GetAnisoBias() const;
u8 GetSignedRemap() const;
// Control0
bool IsEnabled() const;
u16 GetMinLOD() const;
u16 GetMaxLOD() const;
u8 GetMaxAniso() const;
bool IsAlphaKillEnabled() const;
// Control1
u32 GetRemap() const;
// Filter
u16 GetBias() const;
u8 GetMinFilter() const;
u8 GetMagFilter() const;
u8 GetConvolutionFilter() const;
bool isASigned() const;
bool isRSigned() const;
bool isGSigned() const;
bool isBSigned() const;
// Image Rect
u16 GetWidth() const;
u16 GetHeight() const;
void SetControl3(u16 depth, u32 pitch);
};

View File

@ -1,5 +1,6 @@
#pragma once
#include "GCM.h"
#include "RSXTexture.h"
#include "RSXVertexProgram.h"
#include "RSXFragmentProgram.h"
#include "Emu/SysCalls/Callback.h"
@ -15,67 +16,6 @@ enum Method
extern u32 methodRegisters[0xffff];
u32 GetAddress(u32 offset, u8 location);
class RSXTexture
{
u8 m_index;
public:
u32 m_pitch;
u16 m_depth;
public:
RSXTexture();
RSXTexture(u8 index);
void Init();
// Offset
u32 GetOffset() const;
// Format
u8 GetLocation() const;
bool isCubemap() const;
u8 GetBorderType() const;
u8 GetDimension() const;
u8 GetFormat() const;
u16 Getmipmap() const;
// Address
u8 GetWrapS() const;
u8 GetWrapT() const;
u8 GetWrapR() const;
u8 GetUnsignedRemap() const;
u8 GetZfunc() const;
u8 GetGamma() const;
u8 GetAnisoBias() const;
u8 GetSignedRemap() const;
// Control0
bool IsEnabled() const;
u16 GetMinLOD() const;
u16 GetMaxLOD() const;
u8 GetMaxAniso() const;
bool IsAlphaKillEnabled() const;
// Control1
u32 GetRemap() const;
// Filter
u16 GetBias() const;
u8 GetMinFilter() const;
u8 GetMagFilter() const;
u8 GetConvolutionFilter() const;
bool isASigned() const;
bool isRSigned() const;
bool isGSigned() const;
bool isBSigned() const;
// Image Rect
u16 GetWidth() const;
u16 GetHeight() const;
void SetControl3(u16 depth, u32 pitch);
};
struct RSXVertexData
{
u32 frequency;

View File

@ -44,7 +44,7 @@ int cellPngDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t<CellPngDecSrc> s
// Get size of file
MemoryAllocator<CellFsStat> sb; // Alloc a CellFsStat struct
ret = cellFsFstat(current_subHandle->fd, sb);
ret = cellFsFstat(current_subHandle->fd, sb.GetAddr());
if(ret != CELL_OK) return ret;
current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size
break;

View File

@ -190,7 +190,7 @@ void Emulator::Load()
if(IsSelf(m_path.ToStdString()))
{
std::string self_path = m_path;
std::string self_path = m_path.mb_str();
std::string elf_path = wxFileName(m_path).GetPath().c_str();
if(wxFileName(m_path).GetFullName().CmpNoCase("EBOOT.BIN") == 0)

View File

@ -47,7 +47,7 @@ AboutDialog::AboutDialog(wxWindow *parent)
wxBoxSizer* s_panel_credits(new wxBoxSizer(wxHORIZONTAL));
wxStaticText* t_section1 = new wxStaticText(this, wxID_ANY, "\nDevelopers:\n\nDH\nAlexAltea\nHykem\nOil", wxDefaultPosition, wxSize(156,160));
wxStaticText* t_section2 = new wxStaticText(this, wxID_ANY, "\nThanks:\n\nBlackDaemon", wxDefaultPosition, wxSize(156,160));
wxStaticText* t_section3 = new wxStaticText(this, wxID_ANY, "\nExternal code:\n\n - SELF Decrypter based on scetool (C) 2011-2013 by naehrwert\n - PKG Installer based on ps3pkgtool (C) 2011-2013 by avtolstoy and PKG Finalize (C) by geohot", wxDefaultPosition, wxSize(156,160));
wxStaticText* t_section3 = new wxStaticText(this, wxID_ANY, "\nExternal code:\n\n - SELF Decrypter based on scetool (C) 2011-2013 by naehrwert", wxDefaultPosition, wxSize(156,160));
s_panel_credits->AddSpacer(12);
s_panel_credits->Add(t_section1);

View File

@ -127,8 +127,10 @@ CompilerELF::CompilerELF(wxWindow* parent)
" b exit, 0, 0\n"
);
#ifdef _WIN32
::SendMessage((HWND)hex_list->GetHWND(), WM_VSCROLL, SB_BOTTOM, 0);
::SendMessage((HWND)asm_list->GetHWND(), WM_VSCROLL, SB_BOTTOM, 0);
#endif
}
CompilerELF::~CompilerELF()
@ -318,6 +320,7 @@ void CompilerELF::OnScroll(wxScrollWinEvent& event)
dst = hex_list;
}
#ifdef _WIN32
if(!m_disable_scroll && src && dst && event.GetOrientation() == wxVERTICAL)
{
s64 kind = -1;
@ -364,6 +367,7 @@ void CompilerELF::OnScroll(wxScrollWinEvent& event)
m_disable_scroll = false;
}
}
#endif
event.Skip();
}

View File

@ -268,7 +268,9 @@ void LogFrame::Task()
m_log.SetColumnWidth(0, -1); // crashes on exit
m_log.SetColumnWidth(1, -1);
#ifdef _WIN32
::SendMessage((HWND)m_log.GetHWND(), WM_VSCROLL, SB_BOTTOM, 0);
#endif
}
LogBuffer.Flush();

View File

@ -5,7 +5,6 @@
#include "RSXDebugger.h"
#include "git-version.h"
#include "Emu/System.h"
#include "Ini.h"
#include "Emu/GS/sysutil_video.h"
#include "Gui/VHDDManager.h"
@ -13,7 +12,7 @@
#include "Gui/AboutDialog.h"
#include <wx/dynlib.h>
#include "unpkg/unpkg.c"
#include "Loader/PKG.h"
BEGIN_EVENT_TABLE(MainFrame, FrameBase)
EVT_CLOSE(MainFrame::OnQuit)
@ -81,45 +80,50 @@ MainFrame::MainFrame()
wxMenuBar& menubar(*new wxMenuBar());
wxMenu& menu_boot(*new wxMenu());
wxMenu& menu_sys(*new wxMenu());
wxMenu& menu_conf(*new wxMenu());
wxMenu& menu_tools(*new wxMenu());
wxMenu& menu_help(*new wxMenu());
menubar.Append(&menu_boot, "Boot");
menubar.Append(&menu_sys, "System");
menubar.Append(&menu_conf, "Config");
menubar.Append(&menu_tools, "Tools");
menubar.Append(&menu_help, "Help");
menu_boot.Append(id_boot_game, "Boot game");
menu_boot.Append(id_install_pkg, "Install PKG");
menu_boot.AppendSeparator();
menu_boot.Append(id_boot_elf, "Boot (S)ELF");
wxMenu& menu_sys(*new wxMenu());
menubar.Append(&menu_sys, "System");
menu_sys.Append(id_sys_pause, "Pause")->Enable(false);
menu_sys.Append(id_sys_stop, "Stop\tCtrl + S")->Enable(false);
menu_sys.AppendSeparator();
menu_sys.Append(id_sys_send_open_menu, "Send open system menu cmd")->Enable(false);
menu_sys.Append(id_sys_send_exit, "Send exit cmd")->Enable(false);
wxMenu& menu_conf(*new wxMenu());
menubar.Append(&menu_conf, "Config");
menu_conf.Append(id_config_emu, "Settings");
menu_conf.Append(id_config_pad, "PAD Settings");
menu_conf.AppendSeparator();
menu_conf.Append(id_config_vfs_manager, "Virtual File System Manager");
menu_conf.Append(id_config_vhdd_manager, "Virtual HDD Manager");
wxMenu& menu_tools(*new wxMenu());
menubar.Append(&menu_tools, "Tools");
menu_tools.Append(id_tools_compiler, "ELF Compiler");
menu_tools.Append(id_tools_memory_viewer, "Memory Viewer");
menu_tools.Append(id_tools_rsx_debugger, "RSX Debugger");
wxMenu& menu_help(*new wxMenu());
menubar.Append(&menu_help, "Help");
menu_help.Append(id_help_about, "About...");
SetMenuBar(&menubar);
// Panels
m_game_viewer = new GameViewer(this);
m_debugger_frame = new DebuggerPanel(this);
ConLogFrame = new LogFrame(this);
AddPane(m_game_viewer, "Game List", wxAUI_DOCK_BOTTOM);
AddPane(ConLogFrame, "Log", wxAUI_DOCK_BOTTOM);
AddPane(m_debugger_frame, "Debugger", wxAUI_DOCK_RIGHT);
// Events
Connect( id_boot_game, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootGame) );
Connect( id_install_pkg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::InstallPkg) );
Connect( id_boot_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootElf) );
@ -221,43 +225,21 @@ void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event))
return;
}
ConLog.Write("PKG: extracting...");
Emu.Stop();
wxString fileName = ctrl.GetPath();
if (!pkg_unpack(static_cast<const char*>(fileName)))
ConLog.Error("Could not unpack PKG!");
else ConLog.Success("PKG: extract done.");
if (!wxRemoveFile(ctrl.GetPath()+".dec"))
ConLog.Warning("Could not delete the decoded DEC file");
pkg_header *header;
pkg_info(static_cast<const char*>(fileName), &header);
wxString titleID_full (header->title_id);
wxString titleID = titleID_full.SubString(7, 15);
wxString mainDir = wxGetCwd();
wxString gamePath = "\\dev_hdd0\\game\\";
wxString pkgDir = mainDir + gamePath + titleID;
// Save the title ID.
Emu.SetTitleID(titleID);
//Refresh game list
m_game_viewer->Refresh();
if(Emu.BootGame(pkgDir.ToStdString()))
// Open and install PKG file
std::string filePath = ctrl.GetPath();
wxFile pkg_f(filePath, wxFile::read); // TODO: Use VFS to install PKG files
if (pkg_f.IsOpened())
{
ConLog.Success("Game: boot done.");
}
else
{
ConLog.Error("Ps3 executable not found in folder (%s)", pkgDir.wx_str());
PKGLoader pkg(pkg_f);
pkg.Install("/dev_hdd0/game/");
pkg.Close();
}
// Refresh game list
m_game_viewer->Refresh();
}
void MainFrame::BootElf(wxCommandEvent& WXUNUSED(event))

View File

@ -1,9 +1,13 @@
#pragma once
#include "GameViewer.h"
#include "Gui/Debugger.h"
#include "Gui/GameViewer.h"
#include <wx/aui/aui.h>
class MainFrame : public FrameBase
{
DebuggerPanel* m_debugger_frame;
GameViewer* m_game_viewer;
wxAuiManager m_aui_mgr;
AppConnector m_app_connector;

View File

@ -546,7 +546,7 @@ void RSXDebugger::GetTexture()
m_list_texture->SetItem(i, 3, wxString::Format("%dD", render.m_textures[i].GetDimension()));
m_list_texture->SetItem(i, 4, render.m_textures[i].IsEnabled() ? "True" : "False");
m_list_texture->SetItem(i, 5, wxString::Format("0x%x", render.m_textures[i].GetFormat()));
m_list_texture->SetItem(i, 6, wxString::Format("0x%x", render.m_textures[i].Getmipmap()));
m_list_texture->SetItem(i, 6, wxString::Format("0x%x", render.m_textures[i].GetMipmap()));
m_list_texture->SetItem(i, 7, wxString::Format("0x%x", render.m_textures[i].m_pitch));
m_list_texture->SetItem(i, 8, wxString::Format("%dx%d",
render.m_textures[i].GetWidth(),
@ -569,7 +569,7 @@ void RSXDebugger::GetSettings()
LIST_SETTINGS_ADD("Alpha func", !(render.m_set_alpha_func) ? "(none)" : wxString::Format("0x%x (%s)",
render.m_alpha_func,
ParseGCMEnum(render.m_alpha_func, CELL_GCM_ENUM).wx_str()));
ParseGCMEnum(render.m_alpha_func, CELL_GCM_ENUM)));
LIST_SETTINGS_ADD("Blend color", !(render.m_set_blend_color) ? "(none)" : wxString::Format("R:%d, G:%d, B:%d, A:%d",
render.m_blend_color_r,
render.m_blend_color_g,
@ -589,10 +589,10 @@ void RSXDebugger::GetSettings()
LIST_SETTINGS_ADD("Depth bounds", wxString::Format("Min:%f, Max:%f", render.m_depth_bounds_min, render.m_depth_bounds_max));
LIST_SETTINGS_ADD("Depth func", !(render.m_set_depth_func) ? "(none)" : wxString::Format("0x%x (%s)",
render.m_depth_func,
ParseGCMEnum(render.m_depth_func, CELL_GCM_ENUM).wx_str()));
ParseGCMEnum(render.m_depth_func, CELL_GCM_ENUM)));
LIST_SETTINGS_ADD("Draw mode", wxString::Format("%d (%s)",
render.m_draw_mode,
ParseGCMEnum(render.m_draw_mode, CELL_GCM_PRIMITIVE_ENUM).wx_str()));
ParseGCMEnum(render.m_draw_mode, CELL_GCM_PRIMITIVE_ENUM)));
LIST_SETTINGS_ADD("Scissor", wxString::Format("X:%d, Y:%d, W:%d, H:%d",
render.m_scissor_x,
render.m_scissor_y,
@ -600,7 +600,7 @@ void RSXDebugger::GetSettings()
render.m_scissor_h));
LIST_SETTINGS_ADD("Stencil func", !(render.m_set_stencil_func) ? "(none)" : wxString::Format("0x%x (%s)",
render.m_stencil_func,
ParseGCMEnum(render.m_stencil_func, CELL_GCM_ENUM).wx_str()));
ParseGCMEnum(render.m_stencil_func, CELL_GCM_ENUM)));
LIST_SETTINGS_ADD("Surface Pitch A", wxString::Format("0x%x", render.m_surface_pitch_a));
LIST_SETTINGS_ADD("Surface Pitch B", wxString::Format("0x%x", render.m_surface_pitch_b));
LIST_SETTINGS_ADD("Surface Pitch C", wxString::Format("0x%x", render.m_surface_pitch_c));
@ -690,7 +690,7 @@ void RSXDebugger::OnSelectTexture(wxListEvent& event)
UpdateInformation();
}
wxString RSXDebugger::ParseGCMEnum(u32 value, u32 type)
const char* RSXDebugger::ParseGCMEnum(u32 value, u32 type)
{
switch(type)
{

View File

@ -79,7 +79,7 @@ public:
virtual void SetPrograms(wxListEvent& event);
virtual void OnSelectTexture(wxListEvent& event);
wxString ParseGCMEnum(u32 value, u32 type);
const char* ParseGCMEnum(u32 value, u32 type);
wxString DisAsmCommand(u32 cmd, u32 count, u32 currentAddr, u32 ioAddr);

View File

@ -1,7 +1,9 @@
#include "stdafx.h"
#include "Ini.h"
#ifdef _WIN32
#include <wx/msw/iniconf.h>
#endif
Inis Ini;
@ -148,9 +150,13 @@ static wxString WindowInfoToString(const WindowInfo wind)
//Ini
Ini::Ini()
{
#ifdef _WIN32
m_Config = new wxIniConfig( wxEmptyString, wxEmptyString,
wxGetCwd() + "\\rpcs3.ini",
wxEmptyString, wxCONFIG_USE_LOCAL_FILE );
#else
m_Config = new wxConfig("rpcs3");
#endif
}
void Ini::Save(wxString key, int value)
@ -211,4 +217,4 @@ wxString Ini::Load(wxString key, const wxString& def_value)
WindowInfo Ini::Load(wxString key, const WindowInfo& def_value)
{
return StringToWindowInfo(m_Config->Read(key, WindowInfoToString(def_value)));
}
}

248
rpcs3/Loader/PKG.cpp Normal file
View File

@ -0,0 +1,248 @@
#include "stdafx.h"
#include "PKG.h"
#include "scetool/aes.h"
#include "scetool/sha1.h"
#include <wx/progdlg.h>
PKGLoader::PKGLoader(wxFile& f) : pkg_f(f)
{
}
bool PKGLoader::Install(std::string dest, bool show)
{
// Initial checks
if (!pkg_f.IsOpened())
return false;
dest = wxGetCwd() + dest;
if (!dest.empty() && dest.back() != '/')
dest += '/';
if(!LoadHeader(show))
return false;
std::string titleID = std::string(m_header.title_id).substr(7, 9);
std::string decryptedFile = wxGetCwd() + "/dev_hdd1/" + titleID + ".dec";
if (wxDirExists(dest+titleID)) {
wxMessageDialog d_overwrite(NULL, "Another installation was found. Do you want to overwrite it?", "PKG Decrypter / Installer", wxYES_NO|wxCENTRE);
if (d_overwrite.ShowModal() != wxID_YES) {
ConLog.Error("PKG Loader: Another installation found in: %s", wxString(titleID).wx_str());
return false;
}
// TODO: Remove the following two lines and remove the folder dest+titleID
ConLog.Error("PKG Loader: Another installation found in: %s", wxString(titleID).wx_str());
return false;
}
if (!wxMkdir(dest+titleID)) {
ConLog.Error("PKG Loader: Could not make the installation directory: %s", wxString(titleID).wx_str());
return false;
}
// Decrypt the PKG file
wxFile out;
out.Create(decryptedFile, true);
Decrypt(out);
out.Close();
// Unpack the decrypted file
wxFile dec(decryptedFile, wxFile::read);
LoadEntries(dec);
wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, unpacking...", m_entries.size(), 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);
for (const PKGEntry& entry : m_entries)
{
UnpackEntry(dec, entry, dest+titleID+'/');
pdlg.Update(pdlg.GetValue() + 1);
}
pdlg.Update(m_entries.size());
// Delete decrypted file
dec.Close();
wxRemoveFile(decryptedFile);
ConLog.Write("PKG Loader: Package successfully installed in: /dev_hdd0/game/%s", wxString(titleID.c_str()).wx_str());
return true;
}
bool PKGLoader::Close()
{
return pkg_f.Close();
}
bool PKGLoader::LoadHeader(bool show)
{
pkg_f.Seek(0);
if (pkg_f.Read(&m_header, sizeof(PKGHeader)) != sizeof(PKGHeader)) {
ConLog.Error("PKG Loader: Package file is too short!");
return false;
}
if (!CheckHeader())
return false;
return true;
}
bool PKGLoader::CheckHeader()
{
if (m_header.pkg_magic != 0x7F504B47) {
ConLog.Error("PKG Loader: Not a package file!");
return false;
}
switch (m_header.pkg_type)
{
case PKG_RELEASE_TYPE_DEBUG: break;
case PKG_RELEASE_TYPE_RELEASE: break;
default:
ConLog.Error("PKG Loader: Unknown PKG type!");
return false;
}
switch (m_header.pkg_platform)
{
case PKG_PLATFORM_TYPE_PS3: break;
case PKG_PLATFORM_TYPE_PSP: break;
default:
ConLog.Error("PKG Loader: Unknown PKG type!");
return false;
}
if (m_header.header_size != PKG_HEADER_SIZE) {
ConLog.Error("PKG Loader: Wrong header size!");
return false;
}
if (m_header.pkg_size != pkg_f.Length()) {
ConLog.Error("PKG Loader: File size mismatch.");
return false;
}
if (m_header.data_size + m_header.data_offset + 0x60 != pkg_f.Length()) {
ConLog.Error("PKG Loader: Data size mismatch.");
return false;
}
return true;
}
bool PKGLoader::LoadEntries(wxFile& dec)
{
m_entries.resize(m_header.file_count);
dec.Seek(0);
dec.Read(&m_entries[0], sizeof(PKGEntry) * m_header.file_count);
if (m_entries[0].name_offset / sizeof(PKGEntry) != m_header.file_count) {
ConLog.Error("PKG Loader: Entries are damaged!");
return false;
}
return true;
}
bool PKGLoader::UnpackEntry(wxFile& dec, const PKGEntry& entry, std::string dir)
{
u8 buf[BUF_SIZE];
dec.Seek(entry.name_offset);
dec.Read(buf, entry.name_size);
buf[entry.name_size] = 0;
switch (entry.type & (0xffff))
{
case PKG_FILE_ENTRY_NPDRM:
case PKG_FILE_ENTRY_NPDRMEDAT:
case PKG_FILE_ENTRY_SDAT:
case PKG_FILE_ENTRY_REGULAR:
{
wxFile out;
out.Create(dir + buf);
dec.Seek(entry.file_offset);
for (u64 size = 0; size < entry.file_size; ) {
size += dec.Read(buf, BUF_SIZE);
if (size > entry.file_size)
out.Write(buf, BUF_SIZE - (size - entry.file_size));
else
out.Write(buf, BUF_SIZE);
}
out.Close();
}
break;
case PKG_FILE_ENTRY_FOLDER:
wxMkdir(dir + buf);
break;
}
return true;
}
void PKGLoader::Decrypt(wxFile& out)
{
aes_context c;
u8 iv[HASH_LEN];
u8 buf[BUF_SIZE];
u8 ctr[BUF_SIZE];
// Debug key
u8 key[0x40];
memset(key, 0, 0x40);
memcpy(key+0x00, &m_header.qa_digest[0], 8); // &data[0x60]
memcpy(key+0x08, &m_header.qa_digest[0], 8); // &data[0x60]
memcpy(key+0x10, &m_header.qa_digest[8], 8); // &data[0x68]
memcpy(key+0x18, &m_header.qa_digest[8], 8); // &data[0x68]
pkg_f.Seek(m_header.data_offset);
u32 parts = (m_header.data_size + BUF_SIZE - 1) / BUF_SIZE;
wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, decrypting...", parts, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);
memcpy(iv, m_header.klicensee, sizeof(iv));
aes_setkey_enc(&c, PKG_AES_KEY, 128);
for (u32 i=0; i<parts; i++)
{
memset(buf, 0, sizeof(buf));
u32 length = pkg_f.Read(buf, BUF_SIZE);
u32 bits = (length + HASH_LEN - 1) / HASH_LEN;
if (m_header.pkg_type == PKG_RELEASE_TYPE_DEBUG)
{
for (u32 j=0; j<bits; j++)
{
u8 hash[0x14];
sha1(key, 0x40, hash);
*(u64*)&buf[j*HASH_LEN + 0] ^= *(u64*)&hash[0];
*(u64*)&buf[j*HASH_LEN + 8] ^= *(u64*)&hash[8];
*(be_t<u64>*)&key[0x38] += 1;
}
}
if (m_header.pkg_type == PKG_RELEASE_TYPE_RELEASE)
{
for (u32 j=0; j<bits; j++)
{
aes_crypt_ecb(&c, AES_ENCRYPT, iv, ctr+j*HASH_LEN);
be_t<u64> hi = *(be_t<u64>*)&iv[0];
be_t<u64> lo = *(be_t<u64>*)&iv[8] + 1;
if (lo == 0)
hi += 1;
*(be_t<u64>*)&iv[0] = hi;
*(be_t<u64>*)&iv[8] = lo;
}
for (u32 j=0; j<length; j++) {
buf[j] ^= ctr[j];
}
}
out.Write(buf, length);
pdlg.Update(i);
}
pdlg.Update(parts);
}

76
rpcs3/Loader/PKG.h Normal file
View File

@ -0,0 +1,76 @@
#pragma once
#include "Loader.h"
// Constants
#define PKG_HEADER_SIZE 0xC0 //sizeof(pkg_header) + sizeof(pkg_unk_checksum)
#define PKG_RELEASE_TYPE_RELEASE 0x8000
#define PKG_RELEASE_TYPE_DEBUG 0x0000
#define PKG_PLATFORM_TYPE_PS3 0x0001
#define PKG_PLATFORM_TYPE_PSP 0x0002
#define PKG_FILE_ENTRY_NPDRM 0x0001
#define PKG_FILE_ENTRY_NPDRMEDAT 0x0002
#define PKG_FILE_ENTRY_REGULAR 0x0003
#define PKG_FILE_ENTRY_FOLDER 0x0004
#define PKG_FILE_ENTRY_SDAT 0x0009
#define PKG_FILE_ENTRY_OVERWRITE 0x80000000
#define HASH_LEN 16
#define BUF_SIZE 4096
// Key
static const u8 PKG_AES_KEY[16] = {
0x2e, 0x7b, 0x71, 0xd7,
0xc9, 0xc9, 0xa1, 0x4e,
0xa3, 0x22, 0x1f, 0x18,
0x88, 0x28, 0xb8, 0xf8
};
// Structs
struct PKGHeader
{
be_t<u32> pkg_magic; // Magic (0x7f504b47)
be_t<u16> pkg_type; // Release type (Retail:0x8000, Debug:0x0000)
be_t<u16> pkg_platform; // Platform type (PS3:0x0001, PSP:0x0002)
be_t<u32> header_size; // Header size (0xc0)
be_t<u32> unk1; // Some PKG version maybe?
be_t<u32> meta_size; // Size of metadata (block after header & hashes)
be_t<u32> file_count; // Number of files
be_t<u64> pkg_size; // PKG size in bytes
be_t<u64> data_offset; // Encrypted data offset
be_t<u64> data_size; // Encrypted data size in bytes
char title_id[48]; // Title ID
u8 qa_digest[16]; // This should be the hash of "files + attribs"
u8 klicensee[16]; // Nonce
};
struct PKGEntry
{
be_t<u32> name_offset; // File name offset
be_t<u32> name_size; // File name size
be_t<u64> file_offset; // File offset
be_t<u64> file_size; // File size
be_t<u32> type; // File type
be_t<u32> pad; // Padding (zeros)
};
class PKGLoader
{
wxFile& pkg_f;
PKGHeader m_header;
std::vector<PKGEntry> m_entries;
virtual void Decrypt(wxFile& out);
public:
PKGLoader(wxFile& f);
virtual bool Install(std::string dest, bool show = false);
virtual bool LoadHeader(bool show = false);
virtual bool CheckHeader();
virtual bool LoadEntries(wxFile& dec);
virtual bool UnpackEntry(wxFile& dec, const PKGEntry& entry, std::string dir);
virtual bool Close();
};

View File

@ -2,8 +2,10 @@
#include "rpcs3.h"
#include "Ini.h"
#include "Emu/System.h"
#ifdef _WIN32
#include <wx/msw/wrapwin.h>
#include "Gui/CompilerELF.h"
#endif
const wxEventType wxEVT_DBG_COMMAND = wxNewEventType();
@ -22,15 +24,7 @@ bool Rpcs3App::OnInit()
SetTopWindow(m_MainFrame);
Emu.Init();
// (new CompilerELF(m_MainFrame))->Show();
m_debugger_frame = new DebuggerPanel(m_MainFrame);
ConLogFrame = new LogFrame(m_MainFrame);
m_MainFrame->AddPane(ConLogFrame, "Log", wxAUI_DOCK_BOTTOM);
m_MainFrame->AddPane(m_debugger_frame, "Debugger", wxAUI_DOCK_RIGHT);
//ConLogFrame->Show();
m_MainFrame->Show();
m_MainFrame->DoSettings(true);
return true;

View File

@ -1,7 +1,6 @@
#pragma once
#include "Gui/MainFrame.h"
#include "Gui/Debugger.h"
template<typename T> T min(const T a, const T b) { return a < b ? a : b; }
template<typename T> T max(const T a, const T b) { return a > b ? a : b; }
@ -55,7 +54,6 @@ class Rpcs3App : public wxApp
{
public:
MainFrame* m_MainFrame;
DebuggerPanel* m_debugger_frame;
virtual bool OnInit();
virtual void Exit();

View File

@ -321,6 +321,7 @@
<ClCompile Include="Loader\ELF32.cpp" />
<ClCompile Include="Loader\ELF64.cpp" />
<ClCompile Include="Loader\Loader.cpp" />
<ClCompile Include="Loader\PKG.cpp" />
<ClCompile Include="Loader\PSF.cpp" />
<ClCompile Include="Loader\SELF.cpp" />
<ClCompile Include="Loader\TRP.cpp" />

View File

@ -415,6 +415,9 @@
<ClCompile Include="Emu\SysCalls\Modules\cellAdec.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Loader\PKG.cpp">
<Filter>Loader</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="rpcs3.rc" />

View File

@ -1,20 +0,0 @@
#pragma once
#include "stdafx.h"
u8 retail_pkg_aes_key[] = {0x2E,0x7B,0x71,0xD7,0xC9,0xC9,0xA1,0x4E,0xA3,0x22,0x1F,0x18,0x88,0x28,0xB8,0xF8};
u8 npdrm_keypair_e[] = {
0xA1,0xC0,0x13,0xAB,0xCE,0x98,0xA7,0xE3,0xDC,0x69,0x92,0x3B,0x07,0xC0,0x28,0x5F,
0x75,0x54,0xC5,0x12,0xB0,0xB0,0xA9,0x6F,0x24,0x52,0x40,0xF2,0xFD,0x43,0x3A,0xF2,
0x3F,0x4E,0xFE,0xC6,0xC1,0x83,0xEA,0x37,0x8D,0x1B,0xEC,0xB0,0x9D,0x88,0xDB,0x32,
0x8F,0x2C,0x86,0x37,0xB7,0xAC,0x72,0x05,0x9B,0x15,0x56,0xB0,0xD9,0x5B,0x5B,0xE0};
u8 npdrm_keypair_d[] = {
0x87,0xC7,0x4F,0xFE,0x66,0x93,0x0B,0xAA,0xA1,0x6F,0x86,0x40,0x91,0xC5,0x66,0xFB,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x08,0x28,0xB5,0x8F,0xAC,0xF9,0xDE,0xC8,0xD7,0x0D,0xFE,0xF0,0xF3,0x76,0x63,0xAE,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
u8 npdrm_omac_key1[] = {0x72,0xF9,0x90,0x78,0x8F,0x9C,0xFF,0x74,0x57,0x25,0xF0,0x8E,0x4C,0x12,0x83,0x87};
u8 npdrm_omac_key2[] = {0x6B,0xA5,0x29,0x76,0xEF,0xDA,0x16,0xEF,0x3C,0x33,0x9F,0xB2,0x97,0x1E,0x25,0x6B};
u8 npdrm_omac_key3[] = {0x9B,0x51,0x5F,0xEA,0xCF,0x75,0x06,0x49,0x81,0xAA,0x60,0x4D,0x91,0xA5,0x4E,0x97};

View File

@ -1,106 +0,0 @@
#pragma once
#include "stdafx.h"
typedef struct {
u32 magic;
u32 debugFlag;
u32 infoOffset;
u32 unknown1;
u32 headSize;
u32 itemCount;
u64 packageSize;
u64 dataOffset;
u64 dataSize;
} pkg_header2;
u64 get_u64(void* vd) {
u8 *d = (u8*)vd;
return ((u64)d[0]<<56) | ((u64)d[1]<<48) | ((u64)d[2]<<40) | ((u64)d[3]<<32) | (d[4]<<24) | (d[5]<<16) | (d[6]<<8) | d[7];
}
void set_u64(void* vd, u64 v) {
u8 *d = (u8*)vd;
d[0] = v>>56;
d[1] = v>>48;
d[2] = v>>40;
d[3] = v>>32;
d[4] = v>>24;
d[5] = v>>16;
d[6] = v>>8;
d[7] = v>>0;
}
void set_u32(void* vd, u32 v) {
u8 *d = (u8*)vd;
d[0] = v>>24;
d[1] = v>>16;
d[2] = v>>8;
d[3] = v>>0;
}
void set_u16(void* vd, u16 v) {
u8 *d = (u8*)vd;
d[0] = v>>8;
d[1] = v>>0;
}
u32 get_u32(void* vd) {
u8 *d = (u8*)vd;
return (d[0]<<24) | (d[1]<<16) | (d[2]<<8) | d[3];
}
float get_float(u8* d) {
float ret;
u32 inter = (d[0]<<24) | (d[1]<<16) | (d[2]<<8) | d[3];
memcpy(&ret, &inter, 4);
return ret;
}
u32 get_u16(void* vd) {
u8 *d = (u8*)vd;
return (d[0]<<8) | d[1];
}
void hexdump(u8* d, int l) {
int i;
for(i=0;i<l;i++) {
if(i!=0 && (i%16)==0) ConLog.Write("\n");
ConLog.Write("%2.2X ", d[i]);
}
ConLog.Write("\n");
}
void hexdump_nl(u8* d, int l) {
int i;
for(i=0;i<l;i++) {
ConLog.Write("%2.2X ", d[i]);
}
ConLog.Write("\n");
}
void hexdump_ns(u8* d, int l) {
int i;
for(i=0;i<l;i++) {
ConLog.Write("%2.2X", d[i]);
}
}
void hexdump_c(u8* d, int l) {
int i;
for(i=0;i<l;i++) {
ConLog.Write("0x%2.2X", d[i]);
if(i!=(l-1)) {
ConLog.Write(",");
}
}
}
void hexdump_32(u8* d, int l) {
int i;
for(i=0;i<l;i+=4) {
if(i!=0 && (i%16)==0) printf("\n");
ConLog.Write("%8X ", get_u32(d+i));
}
ConLog.Write("\n");
}

View File

@ -1,435 +0,0 @@
/*
* Copyright 2011 Andrey Tolstoy <avtolstoy@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "unpkg.h"
#include "ps3_common.h"
#include "oddkeys.h"
#include <wx/progdlg.h> //in a *.c file ?
static void hash_tostring(char *str, u8 *hash, u32 len)
{
u8 *p;
memset(str, 0, 2*len+1);
for (p = hash; p-hash < len; p++)
{
str += 2;
}
}
static void *pkg_open(const char *fname)
{
FILE *f;
f = fopen(fname, "rb");
if (f == NULL)
{
ConLog.Error ("UnPkg: Could not open package file!");
return NULL;
}
return f;
}
static int pkg_sanity_check(FILE *f, FILE *g, pkg_header **h_ptr, const char *fname)
{
pkg_header *header = (pkg_header*)malloc(sizeof(pkg_header));
u64 tmp;
if (!fread(header, sizeof(pkg_header), 1, f))
{
ConLog.Error("UnPkg: Package file is too short!");
return 1;
}
// some sanity checks
if (ntohl(header->magic) != PKG_MAGIC)
{
ConLog.Error("UnPkg: Not a package file!");
return 1;
}
switch (ntohl(header->rel_type) >> 16 & (0xffff))
{
case PKG_RELEASE_TYPE_DEBUG:
{
ConLog.Warning ("UnPkg: Debug PKG detected.");
wxProgressDialog pdlg ("PKG Decrypter / Installer", "Please wait, recrypting...", 0, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);
u8* data;
u8 sha_key[0x40];
int i;
f= fopen(fname, "rb");
_fseeki64(f, 0, SEEK_END);
int nlen = _ftelli64(f);
_fseeki64(f, 0, SEEK_SET);
data = (u8*)malloc(nlen);
fread(data, 1, nlen, f);
fclose(f);
pkg_header2 *header = (pkg_header2 *)data;
int data_offset = get_u64(&(header->dataOffset));
int data_size = get_u64(&(header->dataSize));
// decrypt debug
u8 sha_crap[0x40];
memset(sha_crap, 0, 0x40);
memcpy(sha_crap, &data[0x60], 8);
memcpy(sha_crap+0x8, &data[0x60], 8);
memcpy(sha_crap+0x10, &data[0x68], 8);
memcpy(sha_crap+0x18, &data[0x68], 8);
int dptr;
for(dptr = data_offset; dptr < (data_offset+data_size); dptr+=0x10) {
u8 hash[0x14];
sha1(sha_crap, 0x40, hash);
for(i=0;i<0x10;i++) data[dptr+i] ^= hash[i];
set_u64(sha_crap+0x38, get_u64(sha_crap+0x38)+1);
}
// recrypt retail
u8 pkg_key[0x10];
memcpy(pkg_key, &data[0x70], 0x10);
//AES_KEY aes_key;
aes_context aes_key;
aes_setkey_enc(&aes_key, retail_pkg_aes_key, 128);
size_t num=0; u8 ecount_buf[0x10]; memset(ecount_buf, 0, 0x10);
aes_crypt_ctr(&aes_key, data_size, &num, pkg_key, ecount_buf, &data[data_offset], &data[data_offset]);
// write back
g = fopen(fname, "wb");
data[4] = 0x80; // set finalize flag
memset(&data[(data_offset+data_size)], 0, 0x60);
// add hash
sha1(data, nlen-0x20, &data[nlen-0x20]);
fwrite(data, 1, nlen, g);
//fclose(g); // not close the file for continuing
_fseeki64(g, 0, SEEK_END);
tmp = _ftelli64(g);
}
break;
case PKG_RELEASE_TYPE_RELEASE:
{
ConLog.Warning ("UnPkg: Retail PKG detected.");
_fseeki64(f, 0, SEEK_END);
tmp = _ftelli64(f);
}
break;
default:
ConLog.Error("UnPkg: Unknown release type.");
return 1;
}
switch (ntohl(header->rel_type) & (0xffff))
{
case PKG_PLATFORM_TYPE_PS3:
case PKG_PLATFORM_TYPE_PSP:
break;
default:
ConLog.Error("UnPkg: Unknown platform type.");
return 1;
}
if (ntohl(header->header_size) != PKG_HEADER_SIZE)
{
ConLog.Error("UnPkg: Wrong header size: ");
return 1;
}
//fseek(g, 0, SEEK_END);
//tmp = ftell(g);
if (ntohll(header->pkg_size) != tmp)
{
ConLog.Error("UnPkg: File size mismatch.");
return 1;
}
tmp -= ntohll(header->data_offset) + 0x60;
if (ntohll(header->data_size) != tmp)
{
ConLog.Error("UnPkg: Data size mismatch.");
return 1;
}
if (h_ptr != NULL)
{
(*h_ptr) = (pkg_header*) malloc(sizeof(pkg_header));
memcpy(h_ptr, &header, sizeof(pkg_header*));
}
return 0;
}
static void print_pkg_header(pkg_header *header)
{
char qa[33], kl[33];
if (header == NULL)
return;
hash_tostring(qa, header->qa_digest, sizeof(header->qa_digest));
hash_tostring(kl, header->klicensee, sizeof(header->klicensee));
ConLog.Write("Magic: 0x%x", ntohl(header->magic));
ConLog.Write("Release Type: 0x%x", ntohl(header->rel_type) >> 16 & (0xffff));
ConLog.Write("Platform Type: 0x%x", ntohl(header->rel_type) & (0xffff));
ConLog.Write("Header size: 0x%x", ntohl(header->header_size));
ConLog.Write("Unk1: 0x%x", ntohl(header->unk1));
ConLog.Write("Metadata size: 0x%x", ntohl(header->meta_size));
ConLog.Write("File count: %u", ntohl(header->file_count));
ConLog.Write("Pkg size: %llu", ntohll(header->pkg_size));
ConLog.Write("Data offset: 0x%llx", ntohll(header->data_offset));
ConLog.Write("Data size: 0x%llu", ntohll(header->data_size));
ConLog.Write("TitleID: %s", wxString(header->title_id, 48).wx_str());
ConLog.Write("QA Digest: %s", wxString(qa, 33).wx_str());
ConLog.Write("KLicensee: %s", wxString(kl, 33).wx_str());
}
static void *pkg_info(const char *fname, pkg_header **h_ptr)
{
FILE *f;
pkg_header *header;
f = (FILE*) pkg_open(fname);
if (f == NULL)
return NULL;
if (pkg_sanity_check(f, NULL, &header, fname))
return NULL;
print_pkg_header(header);
if (h_ptr != NULL)
{
(*h_ptr) = header;
}
else
{
free(header);
}
return f;
}
static void pkg_crypt(const u8 *key, const u8 *kl, FILE *f,
u64 len, FILE *out)
{
aes_context c;
u32 parts, bits;
u32 i, j;
u8 iv[HASH_LEN];
u8 buf[BUF_SIZE];
u8 ctr[BUF_SIZE];
u8 out_buf[BUF_SIZE];
u32 l;
u64 hi, lo;
int max = len / BUF_SIZE;
wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, decrypting...", max, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);
parts = len / BUF_SIZE;
if (len % BUF_SIZE != 0)
parts++;
memcpy(iv, kl, sizeof(iv));
aes_setkey_enc(&c, key, 128);
for (i = 0; i<parts; i++)
{
l = fread(buf, 1, BUF_SIZE, f);
bits = l / HASH_LEN;
if (bits % HASH_LEN != 0)
bits++;
for (j = 0; j<bits; j++)
{
aes_crypt_ecb(&c, AES_ENCRYPT, iv, ctr+j*HASH_LEN);
hi = unpack64(iv);
lo = unpack64(iv+8) + 1;
if (lo == 0)
hi++;
pack64(iv, hi);
pack64(iv + 8, lo);
}
memset(out_buf, 0, sizeof(out_buf));
for (j=0; j<l; j++)
{
out_buf[j] = buf[j] ^ ctr[j];
}
fwrite(out_buf, 1, l, out);
pdlg.Update(i);
}
pdlg.Update(max);
}
static bool pkg_unpack_file(pkg_file_entry *fentry, FILE *dec)
{
FILE *out = NULL;
u64 size;
u32 tmp;
u8 buf[BUF_SIZE];
_fseeki64(dec, fentry->name_offset, SEEK_SET);
memset(buf, 0, sizeof(buf));
fread(buf, fentry->name_size, 1, dec);
switch (fentry->type & (0xffff))
{
case PKG_FILE_ENTRY_NPDRM:
case PKG_FILE_ENTRY_NPDRMEDAT:
case PKG_FILE_ENTRY_SDAT:
case PKG_FILE_ENTRY_REGULAR:
out = fopen((char *)buf, "wb");
_fseeki64(dec, fentry->file_offset, SEEK_SET);
for (size = 0; size < fentry->file_size; )
{
size += fread(buf, sizeof(u8), BUF_SIZE, dec);
if (size > fentry->file_size)
tmp = size - fentry->file_size;
else
tmp = 0;
fwrite(buf, sizeof(u8), BUF_SIZE - tmp, out);
}
fclose(out);
break;
case PKG_FILE_ENTRY_FOLDER:
mkdir ((char *)buf);
break;
}
return true;
}
static void pkg_unpack_data(u32 file_count, FILE *dec)
{
int max = file_count;
wxProgressDialog pdlg ("PKG Decrypter / Installer", "Please wait, unpacking...", max, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);
u32 i;
pkg_file_entry *file_table = NULL;
_fseeki64(dec, 0, SEEK_SET);
file_table = (pkg_file_entry *)malloc(sizeof(pkg_file_entry)*file_count);
i = fread(file_table, sizeof(pkg_file_entry), file_count, dec);
if (ntohl(file_table->name_offset) / sizeof(pkg_file_entry) != file_count)
{
ConLog.Error("UnPkg: ERROR. Impossiburu!");
return;
}
for (i = 0; i<file_count; i++)
{
(file_table+i)->name_offset = ntohl((file_table+i)->name_offset);
(file_table+i)->name_size = ntohl((file_table+i)->name_size);
(file_table+i)->file_offset = ntohll((file_table+i)->file_offset);
(file_table+i)->file_size = ntohll((file_table+i)->file_size);
(file_table+i)->type = ntohl((file_table+i)->type);
if(pkg_unpack_file(file_table+i, dec)) pdlg.Update(i);
}
free(file_table);
pdlg.Update(max);
}
bool pkg_unpack(const char *fname)
{
FILE *f, *dec;
char *dec_fname;
pkg_header *header;
struct stat sb;
f = (FILE*) pkg_info(fname, &header);
if (f == NULL)
return false;
// Save the main dir.
wxString mainDir = wxGetCwd();
// Set the working directory.
wxSetWorkingDirectory(wxGetCwd() + "\\dev_hdd0\\game\\");
std::string gamePath = "\\dev_hdd0\\game\\";
// Get the PKG title ID from the header and format it (should match TITLE ID from PARAM.SFO).
std::string titleID_full (header->title_id);
std::string titleID = titleID_full.substr(7, 9);
std::string pkgDir = mainDir + gamePath + titleID;
_fseeki64(f, ntohll(header->data_offset), SEEK_SET);
dec_fname = (char*)malloc(strlen(fname)+4);
memset(dec_fname, 0, strlen(fname)+4);
sprintf(dec_fname, "%s.dec", fname);
dec = fopen(dec_fname, "wb+");
if (dec == NULL)
{
ConLog.Error("UnPkg: Could not create temp file for decrypted data.");
free(header);
return false;
}
unlink(dec_fname);
pkg_crypt(PKG_AES_KEY, header->klicensee, f, ntohll(header->data_size),
dec);
_fseeki64(dec, 0, SEEK_SET);
fclose(f);
if (stat(header->title_id, &sb) != 0)
{
if (mkdir(titleID.c_str()) < 0)
{
ConLog.Error("UnPkg: Could not mkdir.");
ConLog.Error("UnPkg: Possibly, folder already exists in dev_hdd0\\game : %s", wxString(titleID).wx_str());
wxSetWorkingDirectory(mainDir);
free(header);
return false;
}
}
chdir(titleID.c_str());
pkg_unpack_data(ntohl(header->file_count), dec);
fclose(dec);
wxSetWorkingDirectory(mainDir);
return true;
}

View File

@ -1,180 +0,0 @@
/*
* Copyright 2011 Andrey Tolstoy <avtolstoy@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef UNPKG_H_
#define UNPKG_H_
#include "stdafx.h"
#include "scetool/aes.h"
#include "scetool/sha1.h"
#ifdef __GNUG__
#include <arpa/inet.h>
#endif
#define ntohll(x) (((u64) ntohl (x) << 32) | (u64) ntohl (x >> 32) )
#define htonll(x) (((u64) htonl (x) << 32) | (u64) htonl (x >> 32) )
#define conv_ntohl(x) { x = ntohl(x); }
#define conv_ntohll(x) { x = ntohll(x); }
#define conv_htonl(x) { x = htonl(x); }
#define conv_htonll(x) { x = htonll(x); }
#define unpack32(x) ((u32) ((u32)*(x) << 24 | \
(u32)*(x+1) << 16 | \
(u32)*(x+2) << 8 | \
(u32)*(x+3) << 0))
#define unpack64(x) ((u64)unpack32(x) << 32 | (u64)unpack32(x+4))
#define pack32(x, p) \
{ \
*(x) = (u8)(p >> 24); \
*((x)+1) = (u8)(p >> 16); \
*((x)+2) = (u8)(p >> 8); \
*((x)+3) = (u8)(p >> 0); \
}
#define pack64(x, p) { pack32((x + 4), p); pack32((x), p >> 32); }
#define HASH_LEN 16
#define BUF_SIZE 4096
typedef struct {
u32 magic; // magic 0x7f504b47
u32 rel_type; // release type
u32 header_size; // 0xc0
u32 unk1; //some pkg version maybe
u32 meta_size; //size of metadata (block after header & hashes)
u32 file_count; // number of files
u64 pkg_size; // pkg size in bytes
u64 data_offset; // encrypted data offset
u64 data_size; // encrypted data size in bytes
char title_id[48]; // title id
u8 qa_digest[16]; // this should be the hash of "files + attribs"
u8 klicensee[16]; // nonce
} pkg_header;
typedef struct {
u8 hash1[16];
u8 hash2[16];
u8 hash3[16];
u8 hash4[16];
} pkg_unk_checksum;
/*
is it in meta or sfo?
# CATEGORY : HG
# BOOTABLE : YES
# VERSION : 01.00
# APP_VER : 01.00
# PS3_SYSTEM_VER : 03.0000
*/
/* meta hell structure */
typedef struct {
u32 unk1;
u32 unk2;
u32 drm_type;
u32 unk3;
u32 unk4;
u32 unk5;
u32 unk6;
u32 unk7;
u32 unk8;
u32 unk9;
u32 unk10;
u32 unk11;
u32 data_size;
u32 unk12;
u32 unk13;
u32 packager;
u8 unk14[64];
} pkg_meta;
typedef struct {
u32 name_offset; // file name offset
u32 name_size; // file name size
u64 file_offset; // file offset
u64 file_size; // file size
u32 type; // file type
/*
0x80000003 - regular file
0x80000001 - npdrm
0x80000004 - folder
0x80000009 - sdat ?
0x80000002 - npdrm.edat ?
*/
u32 pad; // padding (zeros)
} pkg_file_entry;
typedef struct {
pkg_file_entry fe;
char *name;
char *path;
} file_table_tr;
#define PKG_MAGIC 0x7f504b47 // \x7fPKG
#define PKG_HEADER_SIZE sizeof(pkg_header) + sizeof(pkg_unk_checksum)
#define PKG_RELEASE_TYPE_RELEASE 0x8000
#define PKG_RELEASE_TYPE_DEBUG 0x0000
#define PKG_PLATFORM_TYPE_PS3 0x0001
#define PKG_PLATFORM_TYPE_PSP 0x0002
#define PKG_FILE_ENTRY_OVERWRITE 0x80000000
#define PKG_FILE_ENTRY_NPDRM 0x0001
#define PKG_FILE_ENTRY_NPDRMEDAT 0x0002 // npdrm.edat
#define PKG_FILE_ENTRY_REGULAR 0x0003
#define PKG_FILE_ENTRY_FOLDER 0x0004
#define PKG_FILE_ENTRY_SDAT 0x0009 // .sdat ?
static const u8 PKG_AES_KEY[16] = {
0x2e, 0x7b, 0x71, 0xd7,
0xc9, 0xc9, 0xa1, 0x4e,
0xa3, 0x22, 0x1f, 0x18,
0x88, 0x28, 0xb8, 0xf8
};
static void hash_tostring(char *str, u8 *hash, u32 len);
static void *pkg_open(const char *fname);
static int pkg_sanity_check(FILE *f, FILE *g, pkg_header **h_ptr, const char *fname);
static void print_pkg_header(pkg_header *header);
static void *pkg_info(const char *fname, pkg_header **h_ptr);
static void pkg_crypt(const u8 *key, const u8 *kl, FILE *f,
u64 len, FILE *out);
bool pkg_unpack(const char *fname);
static void pkg_unpack_data(u32 file_count, FILE *dec);
static bool pkg_unpack_file(pkg_file_entry *fentry, FILE *dec);;
static int pkg_pack_data(file_table_tr *ftr, pkg_file_entry *table,
int file_count, sha1_context *ctx, FILE *out);
static void *pkg_pack_create_filetable(file_table_tr *tr, int file_count,
char **n_table, u32 *n_table_len);
#endif