mirror of
https://github.com/libretro/RetroArch
synced 2025-02-19 21:40:49 +00:00
(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:
parent
60edff831a
commit
90165492a1
171
Makefile.ps3
171
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
|
||||
|
43
Makefile.ps3.salamander
Normal file
43
Makefile.ps3.salamander
Normal 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
|
128
ps3/cellframework2/fileio/logger.c
Normal file
128
ps3/cellframework2/fileio/logger.c
Normal 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));
|
||||
}
|
51
ps3/cellframework2/fileio/logger.h
Normal file
51
ps3/cellframework2/fileio/logger.h
Normal 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
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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
97
ps3/ps3py/crypt.c
Normal 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
821
ps3/ps3py/pkg.py
Normal 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
8
ps3/ps3py/setup.py
Normal 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])
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user