(PS3) Added makefile targets for PS3 CFW - NOTE: SSNES Salamander

doesn't seem to work yet on CFW PS3 - use make pkg-signed-standalone
for now on CFW PS3 until this gets sorted out.
This commit is contained in:
TwinAphex51224 2012-02-27 13:43:44 +01:00
parent 60edff831a
commit 90165492a1
11 changed files with 1310 additions and 115 deletions

View File

@ -1,61 +1,79 @@
# Makefile for SSNES PS3. Somewhat generic and avoids using the odd SDK examples.
SSNES_VERSION = "0.9.4.1"
#which compiler to build with - GCC or SNC
#set to GCC for debug builds for use with debugger
CELL_BUILD_TOOLS = SNC
CELL_SDK ?= /usr/local/cell
CELL_GPU_TYPE = RSX
CELL_PSGL_VERSION = ultra-opt
DEBUG = 0
CELL_BUILD_TOOLS = GCC
DOWNLOAD_SHADERS = 1
STRIPPING_ENABLE = 0
HAVE_SSNES_GL = 0
ifeq ($(shell uname), Linux)
platform := linux
CELL_HOST_PATH = $(CELL_SDK)/host-linux
else
platform := win
CELL_HOST_PATH = $(CELL_SDK)/host-win32
endif
CONTENT_ID_FULL = UP0001-SSNE10000_00-0000000000000001
CONTENT_ID = SSNE10000
ifeq ($(platform),win)
HOST_DIR := host-win32
CELL_SDK := /c/usr/local/cell/
else
HOST_DIR := host-linux
CELL_SDK := /usr/local/cell
endif
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
include $(CELL_MK_DIR)/sdk.makedef.mk
ifeq ($(CELL_BUILD_TOOLS),SNC)
CC = $(CELL_SDK)/$(HOST_DIR)/sn/bin/ps3ppusnc
CXX = $(CC)
LD = $(CELL_SDK)/$(HOST_DIR)/sn/bin/ps3ppuld
else
CC = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-gcc
CXX = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-g++
LD = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-g++
endif
STRIP = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-strip
PPU_TARGET = ssnes.elf
SALAMANDER_TARGET = ssnes-salamander.elf
PPU_TARGET := ssnes.elf
SALAMANDER_TARGET := ssnes-salamander.elf
EBOOT_PATH = ps3/pkg/USRDIR/EBOOT.BIN
CORE_PATH = ps3/pkg/USRDIR/cores/CORE.SELF
LDDIRS = -L. -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/ultra-opt
INCDIRS = -I. -Icommon
MAKE_FSELF_NPDRM = $(CELL_HOST_PATH)/bin/make_fself_npdrm
MAKE_PACKAGE_NPDRM = $(CELL_HOST_PATH)/bin/make_package_npdrm
MAKE_SELF = make_self_npdrm
OBJ = fifo_buffer.o ps3/cellframework2/fileio/file_browser.o ps3/ps3_audio.o ps3/menu.o console/main_wrap.o console/rom_ext.o ps3/ps3_input.o ps3/cellframework2/input/pad_input.o getopt.o ssnes.o driver.o file.o settings.o message.o rewind.o movie.o netplay.o netplay_compat.o gfx/gfx_common.o ps3/ps3_video_psgl.o gfx/shader_cg.o gfx/snes_state.o ups.o bps.o strl.o audio/hermite.o dynamic.o ps3/main.o audio/utils.o conf/config_file.o ps3/image.o
PKG_SCRIPT = ps3/ps3py/pkg.py
PKG_FINALIZE = package_finalize
SALAMANDER_CSRCS = ps3/salamander/main.c conf/config_file.c strl.c
PPU_SRCS = fifo_buffer.c \
ps3/cellframework2/fileio/file_browser.c \
ps3/ps3_audio.c \
ps3/menu.c \
console/main_wrap.c \
console/rom_ext.c \
ps3/ps3_input.c \
ps3/cellframework2/input/pad_input.c \
getopt.c \
ssnes.c \
driver.c \
file.c \
settings.c \
message.c \
rewind.c \
movie.c \
netplay.c \
netplay_compat.c \
gfx/gfx_common.c \
ps3/ps3_video_psgl.c \
gfx/shader_cg.c \
gfx/snes_state.c \
ups.c \
bps.c \
strl.c \
audio/hermite.c \
dynamic.c \
ps3/main.c \
audio/utils.c \
conf/config_file.c \
ps3/image.c
ifeq ($(HAVE_SSNES_GL), 1)
DEFINES = -DHAVE_SSNES_GL
GL_LIBS := -lSSNESGL -lSSNESGLcgc
DEFINES = -DHAVE_SSNES_GL
GL_LIBS := -lSSNESGL -lSSNESGLcgc
else
GL_LIBS := -lPSGL -lPSGLcgc
GL_LIBS := -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/ultra-opt -lPSGL -lPSGLcgc
endif
LIBS = -ldbgfont $(GL_LIBS) -lcgc -lgcm_cmd -lgcm_sys_stub -lsnes -lresc_stub -lm -lio_stub -lfs_stub -lsysutil_stub -lsysutil_game_stub -lsysutil_screenshot_stub -lsysutil_np_stub -lpngdec_stub -ljpgdec_stub -lsysmodule_stub -laudio_stub -lnet_stub -lpthread
PPU_LDLIBS = -ldbgfont $(GL_LIBS) -lcgc -lgcm_cmd -lgcm_sys_stub -lsnes -lresc_stub -lm -lio_stub -lfs_stub -lsysutil_stub -lsysutil_game_stub -lsysutil_screenshot_stub -lsysutil_np_stub -lpngdec_stub -ljpgdec_stub -lsysmodule_stub -laudio_stub -lnet_stub -lpthread
DEFINES += -DSSNES_CONSOLE -DHAVE_OPENGL=1 -DHAVE_CG=1 -DHAVE_FBO=1 -D__CELLOS_LV2__ -DHAVE_CONFIGFILE=1 -DHAVE_NETPLAY=1 -DHAVE_SOCKET_LEGACY=1 -DPACKAGE_VERSION=\"0.9.4.1\" -DHAVE_SCREENSHOTS_BUILTIN=1 -Dmain=ssnes_main
DEFINES += -DSSNES_CONSOLE -DHAVE_OPENGL=1 -DHAVE_CG=1 -DHAVE_FBO=1 -D__CELLOS_LV2__ -DHAVE_CONFIGFILE=1 -DHAVE_NETPLAY=1 -DHAVE_SOCKET_LEGACY=1 -DPACKAGE_VERSION=\"$(SSNES_VERSION)\" -DHAVE_SCREENSHOTS_BUILTIN=1 -Dmain=ssnes_main
ifeq ($(DEBUG), 1)
PPU_OPTIMIZE_LV := -O0 -g
@ -63,38 +81,73 @@ else
PPU_OPTIMIZE_LV := -O3 -g
endif
CFLAGS = $(PPU_OPTIMIZE_LV) $(DEFINES)
CXXFLAGS = $(PPU_OPTIMIZE_LV) $(DEFINES)
PPU_CFLAGS = $(PPU_OPTIMIZE_LV) $(DEFINES)
PPU_CXXFLAGS = $(PPU_OPTIMIZE_LV) $(DEFINES)
all: pkg
EXIST_EBOOT_WILDCARD := $(wildcard $(EBOOT_PATH))
EXIST_CORE_WILDCARD := $(wildcard $(CORE_PATH))
$(PPU_TARGET): $(OBJ)
$(LD) -o $@ $(OBJ) $(LDFLAGS) $(LDDIRS) $(LIBS)
ifeq ($(STRIPPING_ENABLE),1)
$(STRIP) $(PPU_TARGET)
EBOOT_EXISTS = 1
CORE_EXISTS = 1
ifneq ($(strip $(EXIST_EBOOT_WILDCARD)),)
EBOOT_EXISTS = 0
endif
%.o: %.c config.h
$(CC) $(INCDIRS) $(CFLAGS) -c -o $@ $<
ifneq ($(strip $(EXIST_CORE_WILDCARD)),)
CORE_EXISTS = 0
endif
%.o: %.cpp config.h
$(CXX) $(INCDIRS) $(CXXFLAGS) -c -o $@ $<
include $(CELL_MK_DIR)/sdk.target.mk
pkg: $(PPU_TARGET)
.PHONY: create-selfs-npdrm create-npdrm-core create-core create-npdrm-salamander create-npdrm-salamander create-shaders clean-selfs
create-npdrm-core:
$(MAKE_FSELF_NPDRM) $(PPU_TARGET) $(CORE_PATH)
create-core:
$(MAKE_SELF) $(PPU_TARGET) $(CORE_PATH) $(CONTENT_ID)
create-npdrm-salamander:
$(MAKE_FSELF_NPDRM) $(SALAMANDER_TARGET) $(EBOOT_PATH)
create-salamander:
$(MAKE_SELF) $(SALAMANDER_TARGET) $(EBOOT_PATH) $(CONTENT_ID)
create-shaders:
ifeq ($(DOWNLOAD_SHADERS),1)
rm -rf ps3/pkg/USRDIR/cores/shaders
$(RM) -rf ps3/pkg/USRDIR/cores/shaders
git clone git://github.com/twinaphex/common-shaders.git ps3/pkg/USRDIR/cores/shaders
endif
$(MAKE_FSELF_NPDRM) $(PPU_TARGET) ps3/pkg/USRDIR/cores/CORE.SELF
$(CC) -g -L. -ldbgfont -lgcm_cmd -lgcm_sys_stub -lm -lio_stub -lfs_stub -lsysutil_stub -lsysutil_game_stub -lsysutil_np_stub -lsysmodule_stub -lnet_stub $(SALAMANDER_CSRCS) -o $(SALAMANDER_TARGET)
$(MAKE_FSELF_NPDRM) $(SALAMANDER_TARGET) ps3/pkg/USRDIR/EBOOT.BIN
pkg: $(PPU_TARGET) create-shaders create-salamander-npdrm create-npdrm-core
$(MAKE_PACKAGE_NPDRM) ps3/pkg/package.conf ps3/pkg
clean:
rm -f $(SALAMANDER_TARGET)
rm -f $(PPU_TARGET)
rm -f $(OBJ)
rm -f *.pkg
pkg-signed: $(PPU_TARGET) create-shaders create-salamander create-npdrm-core
python2 $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) ps3/pkg/ ssnes-ps3-cfw-$(SSNES_VERSION).pkg
.PHONY: all clean pkg
pkg-signed-standalone: $(PPU_TARGET) create-shaders create-core
$(MAKE_SELF) $(PPU_TARGET) $(EBOOT_PATH) $(CONTENT_ID)
python2 $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) ps3/pkg/ ssnes-ps3-cfw-$(SSNES_VERSION).pkg
pkg-signed-cfw: $(PPU_TARGET) create-shaders create-salamander create-core
python2 $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) ps3/pkg/ ssnes-ps3-cfw-$(SSNES_VERSION)-kmeaw.pkg
$(PKG_FINALIZE) ssnes-ps3-cfw-$(SSNES_VERSION)-kmeaw.pkg
pkg-signed-cfw-standalone: $(PPU_TARGET) create-shaders create-core
$(MAKE_SELF) $(PPU_TARGET) $(EBOOT_PATH) $(CONTENT_ID)
python2 $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) ps3/pkg/ ssnes-ps3-cfw-$(SSNES_VERSION).pkg
$(PKG_FINALIZE) ssnes-ps3-cfw-$(SSNES_VERSION)-kmeaw.pkg
clean-selfs:
ifeq ($(EBOOT_EXISTS),1)
@echo "WARNING: Couldn't find file to delete: [$(EBOOT_PATH)], skipping this step."
else
rm $(EBOOT_PATH)
endif
ifeq ($(CORE_EXISTS),1)
@echo "WARNING: Couldn't find file to delete: [$(CORE_PATH)], skipping this step."
else
rm $(CORE_PATH)
endif

43
Makefile.ps3.salamander Normal file
View File

@ -0,0 +1,43 @@
CELL_BUILD_TOOLS = SNC
CELL_SDK ?= /usr/local/cell
CELL_GPU_TYPE = RSX
CELL_PSGL_VERSION = opt
HAVE_LOGGER = 0
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
include $(CELL_MK_DIR)/sdk.makedef.mk
MAKE_SELF = make_self_npdrm
PKG_SCRIPT = ps3/ps3py/pkg.py
PKG_FINALIZE = package_finalize
STRIP = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-strip
COPY = cp
MOVE = mv
C = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-gcc
CC = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-g++
PPU_CFLAGS += -I. -O2 -g -DHAVE_EXITSPAWN_NPDRM
PPU_SRCS = ps3/salamander/main.c strl.c conf/config_file.c
ifeq ($(HAVE_LOGGER), 1)
PPU_CFLAGS += -DHAVE_LOGGER
PPU_SRCS += ps3/cellframework2/fileio/logger.c
endif
PPU_TARGET = ssnes-salamander.elf
ifeq ($(CELL_BUILD_TOOLS),SNC)
PPU_CFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 \
-Xunroll=1 -Xautovecreg=1
PPU_CXXFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 \
-Xunroll=1 -Xautovecreg=1
else
PPU_CFLAGS += -funroll-loops
PPU_CXXFLAGS += -funroll-loops
endif
PPU_OPTIMIZE_LV := -O2
PPU_LDLIBS += -lpthread -lm -lnet_stub -lnetctl_stub -lm -ldbgfont_gcm -lgcm_cmd -lgcm_sys_stub -lio_stub -lsysmodule_stub -lsysutil_stub -lsysutil_game_stub -lfs_stub -lsysutil_np_stub
include $(CELL_MK_DIR)/sdk.target.mk

View File

@ -0,0 +1,128 @@
/* -- Cellframework Mk.II - Open framework to abstract the common tasks related to
* PS3 application development.
*
* Copyright (C) 2010-2012
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES 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.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <netex/net.h>
#include <cell/sysmodule.h>
#include <netex/libnetctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/timer.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "logger.h"
#define PC_DEVELOPMENT_IP_ADDRESS "192.168.1.7"
static int g_sid;
static int sock;
static struct sockaddr_in target;
static char sendbuf[4096];
static int if_up_with(int index)
{
int timeout_count = 10;
int state;
int ret;
(void)index;
ret = cellNetCtlInit();
if (ret < 0)
{
printf("cellNetCtlInit() failed(%x)\n", ret);
return (-1);
}
for (;;)
{
ret = cellNetCtlGetState(&state);
if (ret < 0)
{
printf("cellNetCtlGetState() failed(%x)\n", ret);
return (-1);
}
if (state == CELL_NET_CTL_STATE_IPObtained)
break;
sys_timer_usleep(500 * 1000);
timeout_count--;
if (index && timeout_count < 0)
{
printf("if_up_with(%d) timeout\n", index);
return (0);
}
}
sock=socket(AF_INET,SOCK_DGRAM ,0);
target.sin_family = AF_INET;
target.sin_port = htons(3490);
inet_pton(AF_INET, PC_DEVELOPMENT_IP_ADDRESS, &target.sin_addr);
return (0);
}
static int if_down(int sid)
{
(void)sid;
cellNetCtlTerm();
return (0);
}
void logger_init (void)
{
g_sid = if_up_with(1);
}
void logger_shutdown (void)
{
if_down(g_sid);
}
void net_send(const char *__format,...)
{
va_list args;
va_start(args,__format);
vsnprintf(sendbuf,4000,__format, args);
va_end(args);
int len=strlen(sendbuf);
sendto(sock,sendbuf,len,MSG_DONTWAIT,(const struct sockaddr*)&target,sizeof(target));
}

View File

@ -0,0 +1,51 @@
/* -- Cellframework Mk.II - Open framework to abstract the common tasks related to
* PS3 application development.
*
* Copyright (C) 2010-2012
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES 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.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _LOGGER_H_
#define _LOGGER_H_
#define BUFSIZE (64 * 1024)
#define TCPDUMP_FILE (SYS_APP_HOME "/tcpdump.dump")
#define TCPDUMP_STACKSIZE (16 * 1024)
#define TCPDUMP_PRIO (2048)
void logger_init (void);
void logger_shutdown (void);
void net_send(const char *__format,...);
#endif

View File

@ -621,10 +621,10 @@ begin_shutdown:
SceNpDrmKey * k_licensee = NULL;
int ret = sceNpDrmProcessExitSpawn2(k_licensee, g_settings.libsnes, (const char** const)spawn_argv, NULL, (sys_addr_t)spawn_data, 256, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M);
SSNES_LOG("Attempt to load SELF: [%s] (return code: [%x]).\n", g_settings.libsnes, ret);
if(ret == SCE_NP_DRM_ERROR_FORMAT)
if(ret < 0)
{
SSNES_LOG("SELF file is not of NPDRM type, trying another approach to boot it...\n");
exitspawn(g_settings.libsnes, spawn_argv, NULL, NULL, 0, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M);
sys_game_process_exitspawn(g_settings.libsnes, NULL, NULL, NULL, 0, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M);
}
sceNpTerm();

View File

@ -371,7 +371,7 @@ static void browser_render(filebrowser_t * b)
cellDbgFontDraw();
}
static void set_setting_label(menu * menu_obj, int currentsetting)
static void set_setting_label(menu * menu_obj, uint64_t currentsetting)
{
switch(currentsetting)
{
@ -2108,8 +2108,6 @@ void menu_loop(void)
g_console.menu_enable = true;
gl_t * gl = g_gl;
menu_reinit_settings();
if(g_console.emulator_initialized)

View File

@ -719,53 +719,6 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
return true;
}
static void gl_update_resize(void)
{
gl_t * gl = g_gl;
if(!gl)
return;
if (!gl->render_to_tex)
set_viewport(gl, gl->win_width, gl->win_height, false);
else
{
// Check if we have to recreate our FBO textures.
for (int i = 0; i < gl->fbo_pass; i++)
{
// Check proactively since we might suddently get sizes of tex_w width or tex_h height.
if (gl->fbo_rect[i].max_img_width > gl->fbo_rect[i].width ||
gl->fbo_rect[i].max_img_height > gl->fbo_rect[i].height)
{
unsigned img_width = gl->fbo_rect[i].max_img_width;
unsigned img_height = gl->fbo_rect[i].max_img_height;
unsigned max = img_width > img_height ? img_width : img_height;
unsigned pow2_size = next_pow2(max);
gl->fbo_rect[i].width = gl->fbo_rect[i].height = pow2_size;
glBindFramebufferOES(GL_FRAMEBUFFER_OES, gl->fbo[i]);
glBindTexture(GL_TEXTURE_2D, gl->fbo_texture[i]);
glTexImage2D(GL_TEXTURE_2D,
0, GL_ARGB_SCE, gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0, GL_ARGB_SCE,
GL_UNSIGNED_INT_8_8_8_8, NULL);
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, gl->fbo_texture[i], 0);
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status != GL_FRAMEBUFFER_COMPLETE_OES)
SSNES_WARN("Failed to reinit FBO texture.\n");
SSNES_LOG("Recreating FBO texture #%d: %ux%u\n", i, gl->fbo_rect[i].width, gl->fbo_rect[i].height);
}
}
// Go back to what we're supposed to do, render to FBO #0 :D
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, gl->fbo[0]);
set_viewport(gl, gl->fbo_rect[0].img_width, gl->fbo_rect[0].img_height, true);
}
}
static void psgl_deinit(gl_t *gl)
{
glFinish();

97
ps3/ps3py/crypt.c Normal file
View File

@ -0,0 +1,97 @@
#include <Python.h>
static PyObject *sha1_callback = NULL;
static void manipulate(uint8_t *key) {
uint64_t temp = key[0x38] << 56|
key[0x39] << 48|
key[0x3a] << 40|
key[0x3b] << 32|
key[0x3c] << 24|
key[0x3d] << 16|
key[0x3e] << 8|
key[0x3f];
temp++;
key[0x38] = (temp >> 56) & 0xff;
key[0x39] = (temp >> 48) & 0xff;
key[0x3a] = (temp >> 40) & 0xff;
key[0x3b] = (temp >> 32) & 0xff;
key[0x3c] = (temp >> 24) & 0xff;
key[0x3d] = (temp >> 16) & 0xff;
key[0x3e] = (temp >> 8) & 0xff;
key[0x3f] = (temp >> 0) & 0xff;
}
static PyObject* pkg_crypt(PyObject *self, PyObject *args) {
uint8_t *key, *input, *ret;
int key_length, input_length, length;
int remaining, i, offset=0;
PyObject *arglist;
PyObject *result;
if (!PyArg_ParseTuple(args, "s#s#i", &key, &key_length, &input, &input_length, &length))
return NULL;
ret = malloc(length);
remaining = length;
while (remaining > 0) {
int bytes_to_dump = remaining;
if (bytes_to_dump > 0x10)
bytes_to_dump = 0x10;
// outhash = SHA1(listToString(key)[0:0x40])
uint8_t *outHash;
{
arglist = Py_BuildValue("(s#)", key, 0x40);
result = PyObject_CallObject(sha1_callback, arglist);
Py_DECREF(arglist);
if (!result) return NULL;
int outHash_length;
if (!PyArg_Parse(result, "s#", &outHash, &outHash_length)) return NULL;
}
for(i = 0; i < bytes_to_dump; i++) {
ret[offset] = outHash[i] ^ input[offset];
offset++;
}
Py_DECREF(result);
manipulate(key);
remaining -= bytes_to_dump;
}
// Return the encrypted data
PyObject *py_ret = Py_BuildValue("s#", ret, length);
free(ret);
return py_ret;
}
static PyObject *register_sha1_callback(PyObject *self, PyObject *args) {
PyObject *result = NULL;
PyObject *temp;
if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
if (!PyCallable_Check(temp)) {
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
return NULL;
}
Py_XINCREF(temp); /* Add a reference to new callback */
Py_XDECREF(sha1_callback); /* Dispose of previous callback */
sha1_callback = temp; /* Remember new callback */
/* Boilerplate to return "None" */
Py_INCREF(Py_None);
result = Py_None;
}
return result;
}
static PyMethodDef cryptMethods[] = {
{"pkgcrypt", pkg_crypt, METH_VARARGS, "C implementation of pkg.py's crypt function"},
{"register_sha1_callback", register_sha1_callback, METH_VARARGS, "Register a callback to python's SHA1 function, so we don't have to bother with creating our own implementation."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initpkgcrypt(void) {
(void) Py_InitModule("pkgcrypt", cryptMethods);
}

821
ps3/ps3py/pkg.py Normal file
View File

@ -0,0 +1,821 @@
#!/usr/bin/env python
from __future__ import with_statement
import struct, sys
class StructType(tuple):
def __getitem__(self, value):
return [self] * value
def __call__(self, value, endian='<'):
if isinstance(value, str):
return struct.unpack(endian + tuple.__getitem__(self, 0), value[:tuple.__getitem__(self, 1)])[0]
else:
return struct.pack(endian + tuple.__getitem__(self, 0), value)
class Struct(object):
__slots__ = ('__attrs__', '__baked__', '__defs__', '__endian__', '__next__', '__sizes__', '__values__')
int8 = StructType(('b', 1))
uint8 = StructType(('B', 1))
int16 = StructType(('h', 2))
uint16 = StructType(('H', 2))
int32 = StructType(('l', 4))
uint32 = StructType(('L', 4))
int64 = StructType(('q', 8))
uint64 = StructType(('Q', 8))
float = StructType(('f', 4))
def string(cls, len, offset=0, encoding=None, stripNulls=False, value=''):
return StructType(('string', (len, offset, encoding, stripNulls, value)))
string = classmethod(string)
LE = '<'
BE = '>'
__endian__ = '<'
def __init__(self, func=None, unpack=None, **kwargs):
self.__defs__ = []
self.__sizes__ = []
self.__attrs__ = []
self.__values__ = {}
self.__next__ = True
self.__baked__ = False
if func == None:
self.__format__()
else:
sys.settrace(self.__trace__)
func()
for name in func.func_code.co_varnames:
value = self.__frame__.f_locals[name]
self.__setattr__(name, value)
self.__baked__ = True
if unpack != None:
if isinstance(unpack, tuple):
self.unpack(*unpack)
else:
self.unpack(unpack)
if len(kwargs):
for name in kwargs:
self.__values__[name] = kwargs[name]
def __trace__(self, frame, event, arg):
self.__frame__ = frame
sys.settrace(None)
def __setattr__(self, name, value):
if name in self.__slots__:
return object.__setattr__(self, name, value)
if self.__baked__ == False:
if not isinstance(value, list):
value = [value]
attrname = name
else:
attrname = '*' + name
self.__values__[name] = None
for sub in value:
if isinstance(sub, Struct):
sub = sub.__class__
try:
if issubclass(sub, Struct):
sub = ('struct', sub)
except TypeError:
pass
type_, size = tuple(sub)
if type_ == 'string':
self.__defs__.append(Struct.string)
self.__sizes__.append(size)
self.__attrs__.append(attrname)
self.__next__ = True
if attrname[0] != '*':
self.__values__[name] = size[3]
elif self.__values__[name] == None:
self.__values__[name] = [size[3] for val in value]
elif type_ == 'struct':
self.__defs__.append(Struct)
self.__sizes__.append(size)
self.__attrs__.append(attrname)
self.__next__ = True
if attrname[0] != '*':
self.__values__[name] = size()
elif self.__values__[name] == None:
self.__values__[name] = [size() for val in value]
else:
if self.__next__:
self.__defs__.append('')
self.__sizes__.append(0)
self.__attrs__.append([])
self.__next__ = False
self.__defs__[-1] += type_
self.__sizes__[-1] += size
self.__attrs__[-1].append(attrname)
if attrname[0] != '*':
self.__values__[name] = 0
elif self.__values__[name] == None:
self.__values__[name] = [0 for val in value]
else:
try:
self.__values__[name] = value
except KeyError:
raise AttributeError(name)
def __getattr__(self, name):
if self.__baked__ == False:
return name
else:
try:
return self.__values__[name]
except KeyError:
raise AttributeError(name)
def __len__(self):
ret = 0
arraypos, arrayname = None, None
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size] + offset
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arrayname = attrs
arraypos = 0
size = len(self.__values__[attrs[1:]][arraypos])
size = len(self.__values__[attrs])
ret += size
return ret
def unpack(self, data, pos=0):
for name in self.__values__:
if not isinstance(self.__values__[name], Struct):
self.__values__[name] = None
elif self.__values__[name].__class__ == list and len(self.__values__[name]) != 0:
if not isinstance(self.__values__[name][0], Struct):
self.__values__[name] = None
arraypos, arrayname = None, None
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size] + offset
temp = data[pos:pos+size]
if len(temp) != size:
raise StructException('Expected %i byte string, got %i' % (size, len(temp)))
if encoding != None:
temp = temp.decode(encoding)
if stripNulls:
temp = temp.rstrip('\0')
if attrs[0] == '*':
name = attrs[1:]
if self.__values__[name] == None:
self.__values__[name] = []
self.__values__[name].append(temp)
else:
self.__values__[attrs] = temp
pos += size
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arrayname = attrs
arraypos = 0
name = attrs[1:]
self.__values__[attrs][arraypos].unpack(data, pos)
pos += len(self.__values__[attrs][arraypos])
arraypos += 1
else:
self.__values__[attrs].unpack(data, pos)
pos += len(self.__values__[attrs])
else:
values = struct.unpack(self.__endian__+sdef, data[pos:pos+size])
pos += size
j = 0
for name in attrs:
if name[0] == '*':
name = name[1:]
if self.__values__[name] == None:
self.__values__[name] = []
self.__values__[name].append(values[j])
else:
self.__values__[name] = values[j]
j += 1
return self
def pack(self):
arraypos, arrayname = None, None
ret = ''
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size]+offset
if attrs[0] == '*':
if arrayname != attrs:
arraypos = 0
arrayname = attrs
temp = self.__values__[attrs[1:]][arraypos]
arraypos += 1
else:
temp = self.__values__[attrs]
if encoding != None:
temp = temp.encode(encoding)
temp = temp[:size]
ret += temp + ('\0' * (size - len(temp)))
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arraypos = 0
arrayname = attrs
ret += self.__values__[attrs[1:]][arraypos].pack()
arraypos += 1
else:
ret += self.__values__[attrs].pack()
else:
values = []
for name in attrs:
if name[0] == '*':
if arrayname != name:
arraypos = 0
arrayname = name
values.append(self.__values__[name[1:]][arraypos])
arraypos += 1
else:
values.append(self.__values__[name])
ret += struct.pack(self.__endian__+sdef, *values)
return ret
def __getitem__(self, value):
return [('struct', self.__class__)] * value
class SelfHeader(Struct):
__endian__ = Struct.BE
def __format__(self):
self.magic = Struct.uint32
self.headerVer = Struct.uint32
self.flags = Struct.uint16
self.type = Struct.uint16
self.meta = Struct.uint32
self.headerSize = Struct.uint64
self.encryptedSize = Struct.uint64
self.unknown = Struct.uint64
self.AppInfo = Struct.uint64
self.elf = Struct.uint64
self.phdr = Struct.uint64
self.shdr = Struct.uint64
self.phdrOffsets = Struct.uint64
self.sceversion = Struct.uint64
self.digest = Struct.uint64
self.digestSize = Struct.uint64
class AppInfo(Struct):
__endian__ = Struct.BE
def __format__(self):
self.authid = Struct.uint64
self.unknown = Struct.uint32
self.appType = Struct.uint32
self.appVersion = Struct.uint64
import struct
import sys
import hashlib
import os
import getopt
import ConfigParser
import io
import glob
TYPE_NPDRMSELF = 0x1
TYPE_RAW = 0x3
TYPE_DIRECTORY = 0x4
TYPE_OVERWRITE_ALLOWED = 0x80000000
class EbootMeta(Struct):
__endian__ = Struct.BE
def __format__(self):
self.magic = Struct.uint32
self.unk1 = Struct.uint32
self.drmType = Struct.uint32
self.unk2 = Struct.uint32
self.contentID = Struct.uint8[0x30]
self.fileSHA1 = Struct.uint8[0x10]
self.notSHA1 = Struct.uint8[0x10]
self.notXORKLSHA1 = Struct.uint8[0x10]
self.nulls = Struct.uint8[0x10]
class MetaHeader(Struct):
__endian__ = Struct.BE
def __format__(self):
self.unk1 = Struct.uint32
self.unk2 = Struct.uint32
self.drmType = Struct.uint32
self.unk4 = Struct.uint32
self.unk21 = Struct.uint32
self.unk22 = Struct.uint32
self.unk23 = Struct.uint32
self.unk24 = Struct.uint32
self.unk31 = Struct.uint32
self.unk32 = Struct.uint32
self.unk33 = Struct.uint32
self.secondaryVersion = Struct.uint16
self.unk34 = Struct.uint16
self.dataSize = Struct.uint32
self.unk42 = Struct.uint32
self.unk43 = Struct.uint32
self.packagedBy = Struct.uint16
self.packageVersion = Struct.uint16
class DigestBlock(Struct):
__endian__ = Struct.BE
def __format__(self):
self.type = Struct.uint32
self.size = Struct.uint32
self.isNext = Struct.uint64
class FileHeader(Struct):
__endian__ = Struct.BE
def __format__(self):
self.fileNameOff = Struct.uint32
self.fileNameLength = Struct.uint32
self.fileOff = Struct.uint64
self.fileSize = Struct.uint64
self.flags = Struct.uint32
self.padding = Struct.uint32
def __str__(self):
out = ""
out += "[X] File Name: %s [" % self.fileName
if self.flags & 0xFF == TYPE_NPDRMSELF:
out += "NPDRM Self]"
elif self.flags & 0xFF == TYPE_DIRECTORY:
out += "Directory]"
elif self.flags & 0xFF == TYPE_RAW:
out += "Raw Data]"
else:
out += "Unknown]"
if (self.flags & TYPE_OVERWRITE_ALLOWED ) != 0:
out += " Overwrite allowed.\n"
else:
out += " Overwrite NOT allowed.\n"
out += "\n"
out += "[X] File Name offset: %08x\n" % self.fileNameOff
out += "[X] File Name Length: %08x\n" % self.fileNameLength
out += "[X] Offset To File Data: %016x\n" % self.fileOff
out += "[X] File Size: %016x\n" % self.fileSize
out += "[X] Flags: %08x\n" % self.flags
out += "[X] Padding: %08x\n\n" % self.padding
assert self.padding == 0, "I guess I was wrong, this is not padding."
return out
def __repr__(self):
return self.fileName + ("<FileHeader> Size: 0x%016x" % self.fileSize)
def __init__(self):
Struct.__init__(self)
self.fileName = ""
class Header(Struct):
__endian__ = Struct.BE
def __format__(self):
self.magic = Struct.uint32
self.type = Struct.uint32
self.pkgInfoOff = Struct.uint32
self.unk1 = Struct.uint32
self.headSize = Struct.uint32
self.itemCount = Struct.uint32
self.packageSize = Struct.uint64
self.dataOff = Struct.uint64
self.dataSize = Struct.uint64
self.contentID = Struct.uint8[0x30]
self.QADigest = Struct.uint8[0x10]
self.KLicensee = Struct.uint8[0x10]
def __str__(self):
context = keyToContext(self.QADigest)
setContextNum(context, 0xFFFFFFFFFFFFFFFF)
licensee = crypt(context, listToString(self.KLicensee), 0x10)
out = ""
out += "[X] Magic: %08x\n" % self.magic
out += "[X] Type: %08x\n" % self.type
out += "[X] Offset to package info: %08x\n" % self.pkgInfoOff
out += "[ ] unk1: %08x\n" % self.unk1
out += "[X] Head Size: %08x\n" % self.headSize
out += "[X] Item Count: %08x\n" % self.itemCount
out += "[X] Package Size: %016x\n" % self.packageSize
out += "[X] Data Offset: %016x\n" % self.dataOff
out += "[X] Data Size: %016x\n" % self.dataSize
out += "[X] ContentID: '%s'\n" % (nullterm(self.contentID))
out += "[X] QA_Digest: %s\n" % (nullterm(self.QADigest, True))
out += "[X] K Licensee: %s\n" % licensee.encode('hex')
return out
def listToString(inlist):
if isinstance(inlist, list):
return ''.join(["%c" % el for el in inlist])
else:
return ""
def nullterm(str_plus, printhex=False):
if isinstance(str_plus, list):
if printhex:
str_plus = ''.join(["%X" % el for el in str_plus])
else:
str_plus = listToString(str_plus)
z = str_plus.find('\0')
if z != -1:
return str_plus[:z]
else:
return str_plus
def keyToContext(key):
if isinstance(key, list):
key = listToString(key)
key = key[0:16]
largekey = []
for i in range(0, 8):
largekey.append(ord(key[i]))
for i in range(0, 8):
largekey.append(ord(key[i]))
for i in range(0, 8):
largekey.append(ord(key[i+8]))
for i in range(0, 8):
largekey.append(ord(key[i+8]))
for i in range(0, 0x20):
largekey.append(0)
return largekey
#Thanks to anonymous for the help with the RE of this part,
# the x86 mess of ands and ors made my head go BOOM headshot.
def manipulate(key):
if not isinstance(key, list):
return
tmp = listToString(key[0x38:])
tmpnum = struct.unpack('>Q', tmp)[0]
tmpnum += 1
tmpnum = tmpnum & 0xFFFFFFFFFFFFFFFF
setContextNum(key, tmpnum)
def setContextNum(key, tmpnum):
tmpchrs = struct.pack('>Q', tmpnum)
key[0x38] = ord(tmpchrs[0])
key[0x39] = ord(tmpchrs[1])
key[0x3a] = ord(tmpchrs[2])
key[0x3b] = ord(tmpchrs[3])
key[0x3c] = ord(tmpchrs[4])
key[0x3d] = ord(tmpchrs[5])
key[0x3e] = ord(tmpchrs[6])
key[0x3f] = ord(tmpchrs[7])
try:
import pkgcrypt
except:
print ""
print "-----------------"
print "SSNES BUILD ERROR"
print "-----------------"
print "Couldn't make PKG file. Go into the ps3py directory, and type the following:"
print ""
print "python2 setup.py build"
print ""
print "This should create a pkgcrypt.so file in the build/ directory. Move that file"
print "over to the root of the ps3py directory and try running this script again."
def crypt(key, inbuf, length):
if not isinstance(key, list):
return ""
return pkgcrypt.pkgcrypt(listToString(key), inbuf, length);
# Original python (slow) implementation
ret = ""
offset = 0
while length > 0:
bytes_to_dump = length
if length > 0x10:
bytes_to_dump = 0x10
outhash = SHA1(listToString(key)[0:0x40])
for i in range(0, bytes_to_dump):
ret += chr(ord(outhash[i]) ^ ord(inbuf[offset]))
offset += 1
manipulate(key)
length -= bytes_to_dump
return ret
def SHA1(data):
m = hashlib.sha1()
m.update(data)
return m.digest()
pkgcrypt.register_sha1_callback(SHA1)
def getFiles(files, folder, original):
oldfolder = folder
foundFiles = glob.glob( os.path.join(folder, '*') )
sortedList = []
for filepath in foundFiles:
if not os.path.isdir(filepath):
sortedList.append(filepath)
for filepath in foundFiles:
if os.path.isdir(filepath):
sortedList.append(filepath)
for filepath in sortedList:
newpath = filepath.replace("\\", "/")
newpath = newpath[len(original):]
if os.path.isdir(filepath):
folder = FileHeader()
folder.fileName = newpath
folder.fileNameOff = 0
folder.fileNameLength = len(folder.fileName)
folder.fileOff = 0
folder.fileSize = 0
folder.flags = TYPE_OVERWRITE_ALLOWED | TYPE_DIRECTORY
folder.padding = 0
files.append(folder)
getFiles(files, filepath, original)
else:
file = FileHeader()
file.fileName = newpath
file.fileNameOff = 0
file.fileNameLength = len(file.fileName)
file.fileOff = 0
file.fileSize = os.path.getsize(filepath)
file.flags = TYPE_OVERWRITE_ALLOWED | TYPE_RAW
if newpath == "USRDIR/EBOOT.BIN":
file.fileSize = ((file.fileSize - 0x30 + 63) & ~63) + 0x30
file.flags = TYPE_OVERWRITE_ALLOWED | TYPE_NPDRMSELF
file.padding = 0
files.append(file)
def pack(folder, contentid, outname=None):
qadigest = hashlib.sha1()
header = Header()
header.magic = 0x7F504B47
header.type = 0x01
header.pkgInfoOff = 0xC0
header.unk1 = 0x05
header.headSize = 0x80
header.itemCount = 0
header.packageSize = 0
header.dataOff = 0x140
header.dataSize = 0
for i in range(0, 0x30):
header.contentID[i] = 0
for i in range(0,0x10):
header.QADigest[i] = 0
header.KLicensee[i] = 0
metaBlock = MetaHeader()
metaBlock.unk1 = 1 #doesnt change output of --extract
metaBlock.unk2 = 4 #doesnt change output of --extract
metaBlock.drmType = 3 #1 = Network, 2 = Local, 3 = Free, anything else = unknown
metaBlock.unk4 = 2
metaBlock.unk21 = 4
metaBlock.unk22 = 5 #5 == gameexec, 4 == gamedata
metaBlock.unk23 = 3
metaBlock.unk24 = 4
metaBlock.unk31 = 0xE #packageType 0x10 == patch, 0x8 == Demo&Key, 0x0 == Demo&Key (AND UserFiles = NotOverWrite), 0xE == normal, use 0xE for gamexec, and 8 for gamedata
metaBlock.unk32 = 4 #when this is 5 secondary version gets used??
metaBlock.unk33 = 8 #doesnt change output of --extract
metaBlock.secondaryVersion = 0
metaBlock.unk34 = 0
metaBlock.dataSize = 0
metaBlock.unk42 = 5
metaBlock.unk43 = 4
metaBlock.packagedBy = 0x1061
metaBlock.packageVersion = 0
files = []
getFiles(files, folder, folder)
header.itemCount = len(files)
dataToEncrypt = ""
fileDescLength = 0
fileOff = 0x20 * len(files)
for file in files:
alignedSize = (file.fileNameLength + 0x0F) & ~0x0F
file.fileNameOff = fileOff
fileOff += alignedSize
for file in files:
file.fileOff = fileOff
fileOff += (file.fileSize + 0x0F) & ~0x0F
dataToEncrypt += file.pack()
for file in files:
alignedSize = (file.fileNameLength + 0x0F) & ~0x0F
dataToEncrypt += file.fileName
dataToEncrypt += "\0" * (alignedSize-file.fileNameLength)
fileDescLength = len(dataToEncrypt)
for file in files:
if not file.flags & 0xFF == TYPE_DIRECTORY:
path = os.path.join(folder, file.fileName)
fp = open(path, 'rb')
fileData = fp.read()
qadigest.update(fileData)
fileSHA1 = SHA1(fileData)
fp.close()
if fileData[0:9] == "SCE\0\0\0\0\x02\x80":
fselfheader = SelfHeader()
fselfheader.unpack(fileData[0:len(fselfheader)])
appheader = AppInfo()
appheader.unpack(fileData[fselfheader.AppInfo:fselfheader.AppInfo+len(appheader)])
found = False
digestOff = fselfheader.digest
while not found:
digest = DigestBlock()
digest.unpack(fileData[digestOff:digestOff+len(digest)])
if digest.type == 3:
found = True
else:
digestOff += digest.size
if digest.isNext != 1:
break
digestOff += len(digest)
if appheader.appType == 8 and found:
dataToEncrypt += fileData[0:digestOff]
meta = EbootMeta()
meta.magic = 0x4E504400
meta.unk1 = 1
meta.drmType = metaBlock.drmType
meta.unk2 = 1
for i in range(0,min(len(contentid), 0x30)):
meta.contentID[i] = ord(contentid[i])
for i in range(0,0x10):
meta.fileSHA1[i] = ord(fileSHA1[i])
meta.notSHA1[i] = (~meta.fileSHA1[i]) & 0xFF
if i == 0xF:
meta.notXORKLSHA1[i] = (1 ^ meta.notSHA1[i] ^ 0xAA) & 0xFF
else:
meta.notXORKLSHA1[i] = (0 ^ meta.notSHA1[i] ^ 0xAA) & 0xFF
meta.nulls[i] = 0
dataToEncrypt += meta.pack()
dataToEncrypt += fileData[digestOff + 0x80:]
else:
dataToEncrypt += fileData
else:
dataToEncrypt += fileData
dataToEncrypt += '\0' * (((file.fileSize + 0x0F) & ~0x0F) - len(fileData))
header.dataSize = len(dataToEncrypt)
metaBlock.dataSize = header.dataSize
header.packageSize = header.dataSize + 0x1A0
head = header.pack()
qadigest.update(head)
qadigest.update(dataToEncrypt[0:fileDescLength])
QA_Digest = qadigest.digest()
for i in range(0, 0x10):
header.QADigest[i] = ord(QA_Digest[i])
for i in range(0, min(len(contentid), 0x30)):
header.contentID[i] = ord(contentid[i])
context = keyToContext(header.QADigest)
setContextNum(context, 0xFFFFFFFFFFFFFFFF)
licensee = crypt(context, listToString(header.KLicensee), 0x10)
for i in range(0, min(len(contentid), 0x10)):
header.KLicensee[i] = ord(licensee[i])
if outname != None:
outFile = open(outname, 'wb')
else:
outFile = open(contentid + ".pkg", 'wb')
outFile.write(header.pack())
headerSHA = SHA1(header.pack())[3:19]
outFile.write(headerSHA)
metaData = metaBlock.pack()
metaBlockSHA = SHA1(metaData)[3:19]
metaBlockSHAPad = '\0' * 0x30
context = keyToContext([ord(c) for c in metaBlockSHA])
metaBlockSHAPadEnc = crypt(context, metaBlockSHAPad, 0x30)
context = keyToContext([ord(c) for c in headerSHA])
metaBlockSHAPadEnc2 = crypt(context, metaBlockSHAPadEnc, 0x30)
outFile.write(metaBlockSHAPadEnc2)
outFile.write(metaData)
outFile.write(metaBlockSHA)
outFile.write(metaBlockSHAPadEnc)
context = keyToContext(header.QADigest)
encData = crypt(context, dataToEncrypt, header.dataSize)
outFile.write(encData)
outFile.write('\0' * 0x60)
outFile.close()
print header
def usage():
print """usage: [based on revision 1061]
python pkg.py target-directory [out-file]
python pkg.py [options] npdrm-package
-l | --list list packaged files.
-x | --extract extract package.
python pkg.py [options]
--version print revision.
--help print this message."""
def version():
print """pkg.py 0.5"""
def main():
extract = False
list = False
contentid = None
try:
opts, args = getopt.getopt(sys.argv[1:], "hx:dvl:c:", ["help", "extract=", "version", "list=", "contentid="])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit(2)
elif opt in ("-v", "--version"):
version()
sys.exit(2)
elif opt in ("-x", "--extract"):
fileToExtract = arg
extract = True
elif opt in ("-l", "--list"):
fileToList = arg
list = True
elif opt in ("-c", "--contentid"):
contentid = arg
else:
usage()
sys.exit(2)
if extract:
unpack(fileToExtract)
else:
if len(args) == 1 and contentid != None:
pack(args[0], contentid)
elif len(args) == 2 and contentid != None:
pack(args[0], contentid, args[1])
else:
usage()
sys.exit(2)
if __name__ == "__main__":
main()

8
ps3/ps3py/setup.py Normal file
View File

@ -0,0 +1,8 @@
from distutils.core import setup, Extension
module1 = Extension('pkgcrypt', sources = ['crypt.c'])
setup (name = 'pkgcrypt',
version = '1.0',
description = 'C implementation of the crypt function from pkg.py',
ext_modules = [module1])

View File

@ -20,9 +20,11 @@
#include <cell/sysmodule.h>
#include <sysutil/sysutil_gamecontent.h>
#include <sys/process.h>
#ifdef HAVE_EXITSPAWN_NPDRM
#include <netex/net.h>
#include <np.h>
#include <np/drm.h>
#endif
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
@ -35,6 +37,12 @@
#define NP_POOL_SIZE (128*1024)
#define MAX_PATH_LENGTH 1024
#ifdef HAVE_LOGGER
#include "../cellframework2/fileio/logger.h"
#define SSNES_LOG(...) net_send("SSNES Salamander: " __VA_ARGS__);
#define SSNES_ERR(...) net_send("SSNES Salamander [ERROR] :: " __VA_ARGS__);
#define SSNES_WARN(...) net_send("SSNES Salamander [WARN] :: " __VA_ARGS__);
#else
#define SSNES_LOG(...) do { \
fprintf(stderr, "SSNES Salamander: " __VA_ARGS__); \
fflush(stderr); \
@ -49,8 +57,11 @@
fprintf(stderr, "SSNES Salamander [WARN] :: " __VA_ARGS__); \
fflush(stderr); \
} while (0)
#endif
#ifdef HAVE_EXITSPAWN_NPDRM
static uint8_t np_pool[NP_POOL_SIZE];
#endif
char contentInfoPath[MAX_PATH_LENGTH];
char usrDirPath[MAX_PATH_LENGTH];
char LIBSNES_DIR_PATH[MAX_PATH_LENGTH];
@ -263,19 +274,34 @@ static void get_environment_settings (void)
int main(int argc, char *argv[])
{
CellPadData pad_data;
#ifdef HAVE_EXITSPAWN_NPDRM
char spawn_data[256], spawn_data_size[16];
SceNpDrmKey * k_licensee = NULL;
#endif
int ret;
cellSysmoduleLoadModule(CELL_SYSMODULE_IO);
cellSysmoduleLoadModule(CELL_SYSMODULE_FS);
cellSysmoduleLoadModule(CELL_SYSMODULE_SYSUTIL_GAME);
#if defined(HAVE_EXITSPAWN_NPDRM) || defined(HAVE_LOGGER)
cellSysmoduleLoadModule(CELL_SYSMODULE_NET);
#endif
#ifdef HAVE_EXITSPAWN_NPDRM
cellSysmoduleLoadModule(CELL_SYSMODULE_SYSUTIL_NP);
#endif
#if defined(HAVE_EXITSPAWN_NPDRM) || defined(HAVE_LOGGER)
sys_net_initialize_network();
#endif
#ifdef HAVE_LOGGER
logger_init();
#endif
#ifdef HAVE_EXITSPAWN_NPDRM
sceNpInit(NP_POOL_SIZE, np_pool);
#endif
get_environment_settings();
@ -297,6 +323,11 @@ int main(int argc, char *argv[])
cellPadEnd();
#ifdef HAVE_LOGGER
logger_shutdown();
#endif
#ifdef HAVE_EXITSPAWN_NPDRM
for(unsigned int i = 0; i < sizeof(spawn_data); ++i)
spawn_data[i] = i & 0xff;
@ -310,17 +341,29 @@ int main(int argc, char *argv[])
};
ret = sceNpDrmProcessExitSpawn2(k_licensee, libsnes_path, (const char** const)spawn_argv, NULL, (sys_addr_t)spawn_data, 256, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M);
if(ret == SCE_NP_DRM_ERROR_FORMAT)
SSNES_LOG("Launch libsnes core: [%s] (return code: %x]).\n", libsnes_path, ret);
if(ret < 0)
{
SSNES_LOG("SELF file is not of NPDRM type, trying another approach to boot it...\n");
exitspawn(libsnes_path, (const char** const)spawn_argv, NULL, NULL, 0, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M);
sys_game_process_exitspawn2(libsnes_path, NULL, NULL, NULL, 0, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M);
}
SSNES_LOG("Launch libsnes core: [%s] (return code: %x]).\n", libsnes_path, ret);
sceNpTerm();
#else
sys_game_process_exitspawn2((char*)libsnes_path, NULL, NULL, NULL, 0, 1000, SYS_PROCESS_PRIMARY_STACK_SIZE_1M);
#endif
#if defined(HAVE_EXITSPAWN_NPDRM) || defined(HAVE_LOGGER)
sys_net_finalize_network();
#endif
#ifdef HAVE_EXITSPAWN_NPDRM
cellSysmoduleUnloadModule(CELL_SYSMODULE_SYSUTIL_NP);
#endif
#if defined(HAVE_EXITSPAWN_NPDRM) || defined(HAVE_LOGGER)
cellSysmoduleUnloadModule(CELL_SYSMODULE_NET);
#endif
cellSysmoduleUnloadModule(CELL_SYSMODULE_SYSUTIL_GAME);
cellSysmoduleLoadModule(CELL_SYSMODULE_FS);
cellSysmoduleLoadModule(CELL_SYSMODULE_IO);