diff --git a/Makefile.ps3 b/Makefile.ps3
index 9331c1137f..becf79bee3 100644
--- a/Makefile.ps3
+++ b/Makefile.ps3
@@ -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
diff --git a/Makefile.ps3.salamander b/Makefile.ps3.salamander
new file mode 100644
index 0000000000..aa28346a1c
--- /dev/null
+++ b/Makefile.ps3.salamander
@@ -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
diff --git a/ps3/cellframework2/fileio/logger.c b/ps3/cellframework2/fileio/logger.c
new file mode 100644
index 0000000000..0b86fbebac
--- /dev/null
+++ b/ps3/cellframework2/fileio/logger.c
@@ -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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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));
+}
diff --git a/ps3/cellframework2/fileio/logger.h b/ps3/cellframework2/fileio/logger.h
new file mode 100644
index 0000000000..055653f76f
--- /dev/null
+++ b/ps3/cellframework2/fileio/logger.h
@@ -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 .
+ */
+
+#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
diff --git a/ps3/main.c b/ps3/main.c
index b1088a8c89..921ffcc800 100644
--- a/ps3/main.c
+++ b/ps3/main.c
@@ -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();
diff --git a/ps3/menu.c b/ps3/menu.c
index 07f323e689..4639045faf 100644
--- a/ps3/menu.c
+++ b/ps3/menu.c
@@ -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)
diff --git a/ps3/ps3_video_psgl.c b/ps3/ps3_video_psgl.c
index 575fe00960..ff61ce4185 100644
--- a/ps3/ps3_video_psgl.c
+++ b/ps3/ps3_video_psgl.c
@@ -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();
diff --git a/ps3/ps3py/crypt.c b/ps3/ps3py/crypt.c
new file mode 100644
index 0000000000..87a89039ca
--- /dev/null
+++ b/ps3/ps3py/crypt.c
@@ -0,0 +1,97 @@
+#include
+
+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);
+}
+
+
diff --git a/ps3/ps3py/pkg.py b/ps3/ps3py/pkg.py
new file mode 100644
index 0000000000..17cc1aeada
--- /dev/null
+++ b/ps3/ps3py/pkg.py
@@ -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 + (" 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()
diff --git a/ps3/ps3py/setup.py b/ps3/ps3py/setup.py
new file mode 100644
index 0000000000..c315b47e2d
--- /dev/null
+++ b/ps3/ps3py/setup.py
@@ -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])
diff --git a/ps3/salamander/main.c b/ps3/salamander/main.c
index 1833428567..26edac8a3f 100644
--- a/ps3/salamander/main.c
+++ b/ps3/salamander/main.c
@@ -20,9 +20,11 @@
#include
#include
#include
+#ifdef HAVE_EXITSPAWN_NPDRM
#include
#include
#include
+#endif
#include
#include
#include
@@ -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);
| |