Initial commit
231
Makefile
Normal file
@ -0,0 +1,231 @@
|
||||
#options, set 1 to enable
|
||||
CELL_DEBUG = 0
|
||||
CELL_DEBUG_CONSOLE = 0
|
||||
CELL_DEBUG_FPS = 0
|
||||
NO_FRAMESKIP = 0
|
||||
MULTIMAN_SUPPORT = 0
|
||||
TOC_LOG = 0
|
||||
SDK_340 = 1
|
||||
|
||||
#which compiler to build with - GCC or SNC
|
||||
#set to GCC for debug builds for use with debugger
|
||||
CELL_BUILD_TOOLS = SNC
|
||||
|
||||
ifeq ($(CELL_DEBUG),1)
|
||||
PPU_OPTIMIZE_LV := -O0
|
||||
else
|
||||
PPU_OPTIMIZE_LV := -O2
|
||||
endif
|
||||
|
||||
# specify build tools
|
||||
#explicitly set some cell sdk defaults
|
||||
CELL_SDK ?= /usr/local/cell
|
||||
# CELL_GPU_TYPE (currently RSX is only one option)
|
||||
CELL_GPU_TYPE = RSX
|
||||
|
||||
#CELL_PSGL_VERSION is debug, dpm or opt
|
||||
CELL_PSGL_VERSION = opt
|
||||
|
||||
#Python binary - only useful for PSL1ght scripts
|
||||
PYTHONBIN = python2.7
|
||||
|
||||
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
|
||||
include $(CELL_MK_DIR)/sdk.makedef.mk
|
||||
|
||||
# Geohot CFW defines
|
||||
MKSELF_GEOHOT = make_self_npdrm
|
||||
MKPKG_PSLIGHT = buildtools/PS3Py/pkg.py
|
||||
PKG_FINALIZE = package_finalize
|
||||
|
||||
STRIP = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-strip
|
||||
C = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-gcc
|
||||
CC = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-g++
|
||||
|
||||
UTILS_DIR = ./utils
|
||||
SRC_DIR = ./src
|
||||
SNES9X_API_DIR = ./src/snes9x
|
||||
CELL_FRAMEWORK_DIR = ./src/cellframework
|
||||
CELL_FRAMEWORK2_DIR = ./src/cellframework2
|
||||
EBOOT_LAUNCHER_DIR = eboot-launcher
|
||||
|
||||
EMULATOR_VERSION = 1.0
|
||||
|
||||
PPU_SRCS += $(SNES9X_API_DIR)/tile.cpp \
|
||||
$(SNES9X_API_DIR)/cpu.cpp \
|
||||
$(SNES9X_API_DIR)/dma.cpp \
|
||||
$(SNES9X_API_DIR)/ppu.cpp \
|
||||
$(SNES9X_API_DIR)/sa1.cpp \
|
||||
$(SNES9X_API_DIR)/sa1cpu.cpp \
|
||||
$(SNES9X_API_DIR)/fxdbg.cpp \
|
||||
$(SNES9X_API_DIR)/fxemu.cpp \
|
||||
$(SNES9X_API_DIR)/fxinst.cpp \
|
||||
$(SNES9X_API_DIR)/cpuexec.cpp \
|
||||
$(SNES9X_API_DIR)/cpuops.cpp \
|
||||
$(SNES9X_API_DIR)/srtc.cpp \
|
||||
$(SNES9X_API_DIR)/memmap.cpp \
|
||||
$(SNES9X_API_DIR)/apu/apu.cpp \
|
||||
$(SNES9X_API_DIR)/apu/SNES_SPC.cpp \
|
||||
$(foreach dir,$(SNES9X_API_DIR)/jma/,$(wildcard $(dir)/*.cpp)) \
|
||||
$(SNES9X_API_DIR)/bsx.cpp \
|
||||
$(SNES9X_API_DIR)/c4.cpp \
|
||||
$(SNES9X_API_DIR)/c4emu.cpp \
|
||||
$(SNES9X_API_DIR)/cheats.cpp \
|
||||
$(SNES9X_API_DIR)/cheats2.cpp \
|
||||
$(SNES9X_API_DIR)/controls.cpp \
|
||||
$(SNES9X_API_DIR)/crosshairs.cpp \
|
||||
$(SNES9X_API_DIR)/dsp.cpp \
|
||||
$(SNES9X_API_DIR)/dsp1.cpp \
|
||||
$(SNES9X_API_DIR)/dsp2.cpp \
|
||||
$(SNES9X_API_DIR)/dsp3.cpp \
|
||||
$(SNES9X_API_DIR)/dsp4.cpp \
|
||||
$(SNES9X_API_DIR)/globals.cpp \
|
||||
$(SNES9X_API_DIR)/loadzip.cpp \
|
||||
$(SNES9X_API_DIR)/netplay.cpp \
|
||||
$(SNES9X_API_DIR)/obc1.cpp \
|
||||
$(SNES9X_API_DIR)/reader.cpp \
|
||||
$(SNES9X_API_DIR)/sdd1.cpp \
|
||||
$(SNES9X_API_DIR)/sdd1emu.cpp \
|
||||
$(SNES9X_API_DIR)/server.cpp \
|
||||
$(SNES9X_API_DIR)/seta.cpp \
|
||||
$(SNES9X_API_DIR)/seta010.cpp \
|
||||
$(SNES9X_API_DIR)/seta011.cpp \
|
||||
$(SNES9X_API_DIR)/seta018.cpp \
|
||||
$(SNES9X_API_DIR)/snapshot.cpp \
|
||||
$(SNES9X_API_DIR)/snes9x.cpp \
|
||||
$(SNES9X_API_DIR)/spc7110.cpp
|
||||
|
||||
|
||||
PPU_SRCS += $(UTILS_DIR)/zlib/adler32.c \
|
||||
$(UTILS_DIR)/zlib/compress.c \
|
||||
$(UTILS_DIR)/zlib/crc32.c \
|
||||
$(UTILS_DIR)/zlib/deflate.c \
|
||||
$(UTILS_DIR)/zlib/gzclose.c \
|
||||
$(UTILS_DIR)/zlib/gzlib.c \
|
||||
$(UTILS_DIR)/zlib/gzread.c \
|
||||
$(UTILS_DIR)/zlib/gzwrite.c \
|
||||
$(UTILS_DIR)/zlib/infback.c \
|
||||
$(UTILS_DIR)/zlib/inffast.c \
|
||||
$(UTILS_DIR)/zlib/inflate.c \
|
||||
$(UTILS_DIR)/zlib/inftrees.c \
|
||||
$(UTILS_DIR)/zlib/trees.c \
|
||||
$(UTILS_DIR)/zlib/uncompr.c \
|
||||
$(UTILS_DIR)/zlib/zutil.c \
|
||||
$(UTILS_DIR)/zlib/contrib/minizip/ioapi.c \
|
||||
$(UTILS_DIR)/zlib/contrib/minizip/mztools.c \
|
||||
$(UTILS_DIR)/zlib/contrib/minizip/zip.c \
|
||||
$(UTILS_DIR)/zlib/contrib/minizip/unzip.c
|
||||
PPU_SRCS += $(CELL_FRAMEWORK2_DIR)/audio/rsound.c \
|
||||
$(CELL_FRAMEWORK2_DIR)/audio/librsound.c \
|
||||
$(CELL_FRAMEWORK2_DIR)/audio/buffer.c \
|
||||
$(CELL_FRAMEWORK2_DIR)/input/pad_input.c \
|
||||
$(CELL_FRAMEWORK2_DIR)/input/mouse_input.c \
|
||||
|
||||
PPU_SRCS += $(SRC_DIR)/ps3video.cpp \
|
||||
$(SRC_DIR)/snes_state/snes_state.c \
|
||||
$(SRC_DIR)/snes_state/config_file.c \
|
||||
$(SRC_DIR)/menu.cpp \
|
||||
$(CELL_FRAMEWORK2_DIR)/audio/resampler.c \
|
||||
$(CELL_FRAMEWORK2_DIR)/audio/audioport.c \
|
||||
$(SRC_DIR)/ps3input.c \
|
||||
$(SRC_DIR)/emu-ps3.cpp \
|
||||
$(CELL_FRAMEWORK2_DIR)/utility/oskutil.c \
|
||||
$(CELL_FRAMEWORK_DIR)/fileio/FileBrowser.cpp
|
||||
|
||||
PPU_TARGET = snes9x-ps3.ppu.elf
|
||||
|
||||
ifeq ($(CELL_DEBUG),1)
|
||||
DEBUGFLAGS = -D_DEBUG -g
|
||||
else
|
||||
DEBUGFLAGS =
|
||||
endif
|
||||
|
||||
PPU_CFLAGS += -I. -DUSE_FILE32API -Dunix -DPSGL -DCORRECT_VRAM_READS -DRIGHTSHIFT_IS_SAR -DSN_TARGET_PS3 -DNDEBUG=1 -DWORDS_BIGENDIAN -DBLARGG_BIG_ENDIAN=1 -DNO_LOGGER -D__POWERPC__ -D__ppc__ $(DEBUGFLAGS)
|
||||
PPU_CXXFLAGS += -I./src/ -I./src/snes9x/ -DZLIB -DUNZIP_SUPPORT -DJMA_SUPPORT -DPSGL -DCORRECT_VRAM_READS -DRIGHTSHIFT_IS_SAR -DNO_LOGGER -DSN_TARGET_PS3 -DNDEBUG=1 -DWORDS_BIGENDIAN -DBLARGG_BIG_ENDIAN=1 -D__POWERPC__ -D__ppc__ $(DEBUGFLAGS)
|
||||
|
||||
ifeq ($(CELL_BUILD_TOOLS),SNC)
|
||||
PARAMS = -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1 -Xnotocrestore=2 -Xc-=rtti
|
||||
PPU_CFLAGS += $(PARAMS)
|
||||
PPU_CXXFLAGS += $(PARAMS)
|
||||
NOTOCRESTORE = --notocrestore
|
||||
else
|
||||
PPU_CFLAGS += -funroll-loops -fno-rtti
|
||||
PPU_CXXFLAGS += -funroll-loops -fno-rtti
|
||||
NOTOCRESTORE =
|
||||
endif
|
||||
|
||||
ifeq ($(CELL_DEBUG_CONSOLE),1)
|
||||
PPU_CFLAGS += -DCELL_DEBUG_CONSOLE
|
||||
PPU_CXXFLAGS += -DCELL_DEBUG_CONSOLE
|
||||
L_CONTROL_CONSOLE_LDLIBS = -lcontrol_console_ppu
|
||||
L_NET_CTL_LDLIBS = -lnetctl_stub
|
||||
endif
|
||||
|
||||
ifeq ($(CELL_DEBUG_FPS),1)
|
||||
PPU_CFLAGS += -DCELL_DEBUG_FPS
|
||||
PPU_CXXFLAGS += -DCELL_DEBUG_FPS
|
||||
endif
|
||||
|
||||
ifeq ($(NO_FRAMESKIP),1)
|
||||
PPU_CFLAGS += -DNO_FRAMESKIP=1
|
||||
PPU_CXXFLAGS += -DNO_FRAMESKIP=1
|
||||
endif
|
||||
|
||||
ifeq ($(MULTIMAN_SUPPORT),1)
|
||||
PPU_CFLAGS += -DMULTIMAN_SUPPORT=1
|
||||
PPU_CXXFLAGS += -DMULTIMAN_SUPPORT=1
|
||||
ifeq ($(shell uname), Linux)
|
||||
MKFSELF_WC = $(HOME)/bin/make_self_wc
|
||||
else
|
||||
MKFSELF_WC = $(CELL_SDK)/../bin/make_self_wc
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(TOC_LOG),1)
|
||||
TOC_INFO = --print-toc-info
|
||||
else
|
||||
TOC_INFO =
|
||||
endif
|
||||
|
||||
ifeq ($(SDK_340),1)
|
||||
L_SYSUTIL_SCREENSHOT = -lsysutil_screenshot_stub
|
||||
else
|
||||
L_SYSUTIL_SCREENSHOT =
|
||||
endif
|
||||
|
||||
|
||||
PPU_LDLIBS += -L. -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/opt -ldbgfont -lPSGL -lPSGLcgc -lcgc \
|
||||
-lgcm_cmd -lgcm_sys_stub -lresc_stub -lm -lio_stub -lfs_stub -lsysutil_stub -lsysutil_game_stub $(L_SYSUTIL_SCREENSHOT) $(L_CONTROL_CONSOLE_LDLIBS) -lpngdec_stub -ljpgdec_stub \
|
||||
-lsysmodule_stub -laudio_stub -lpthread -lnet_stub $(L_NET_CTL_LDLIBS) $(TOC_INFO) $(NOTOCRESTORE)
|
||||
|
||||
include $(CELL_MK_DIR)/sdk.target.mk
|
||||
|
||||
.PHONY: pkg
|
||||
#standard pkg packaging
|
||||
pkg: $(PPU_TARGET)
|
||||
ifeq ($(MULTIMAN_SUPPORT),1)
|
||||
$(MKFSELF_WC) $(PPU_TARGET) pkg/USRDIR/RELOAD.SELF
|
||||
else
|
||||
$(MAKE_FSELF_NPDRM) $(PPU_TARGET) pkg/USRDIR/EBOOT.BIN
|
||||
endif
|
||||
$(MAKE_PACKAGE_NPDRM) pkg/package.conf pkg
|
||||
|
||||
#massively reduced filesize using MKSELF_GEOHOT - use this for normal jailbreak builds
|
||||
.PHONY: pkg-signed
|
||||
pkg-signed: $(PPU_TARGET)
|
||||
ifeq ($(MULTIMAN_SUPPORT),1)
|
||||
$(MKFSELF_WC) $(PPU_TARGET) pkg/USRDIR/RELOAD.SELF
|
||||
else
|
||||
$(MKSELF_GEOHOT) $(PPU_TARGET) pkg/USRDIR/EBOOT.BIN SNES900000
|
||||
endif
|
||||
$(PYTHONBIN) $(MKPKG_PSLIGHT) --contentid IV0002-SNES90000_00-SAMPLE0000000001 pkg/ snes9xnext-ps3-v$(EMULATOR_VERSION)-fw3.41.pkg
|
||||
|
||||
#use this to create a PKG for use with Geohot CFW 3.55
|
||||
.PHONY: pkg-signed-cfw
|
||||
pkg-signed-cfw:
|
||||
ifeq ($(MULTIMAN_SUPPORT),1)
|
||||
$(MKFSELF_WC) $(PPU_TARGET) pkg/USRDIR/RELOAD.SELF
|
||||
else
|
||||
$(MKSELF_GEOHOT) $(PPU_TARGET) pkg/USRDIR/EBOOT.BIN SNES900000
|
||||
endif
|
||||
$(PYTHONBIN) $(MKPKG_PSLIGHT) --contentid IV0002-SNES90000_00-SAMPLE0000000001 pkg/ snes9xnext-ps3-v$(EMULATOR_VERSION)-cfw3.55.pkg
|
||||
$(PKG_FINALIZE) snes9xnext-ps3-v$(EMULATOR_VERSION)-cfw3.55.pkg
|
69
Makefile-eboot-launcher
Normal file
@ -0,0 +1,69 @@
|
||||
# specify build tools
|
||||
CELL_BUILD_TOOLS = SNC
|
||||
#explicitly set some cell sdk defaults
|
||||
CELL_SDK ?= /usr/local/cell
|
||||
# CELL_GPU_TYPE (currently RSX is only one option)
|
||||
CELL_GPU_TYPE = RSX
|
||||
#CELL_PSGL_VERSION is debug, dpm or opt
|
||||
CELL_PSGL_VERSION = opt
|
||||
|
||||
#Python binary - only useful for PSL1ght scripts
|
||||
PYTHONBIN = python2.7
|
||||
|
||||
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
|
||||
include $(CELL_MK_DIR)/sdk.makedef.mk
|
||||
#CELL_HOST_PATH ?= $(CELL_SDK)/host-win32
|
||||
MKFSELF = $(CELL_HOST_PATH)/bin/make_fself
|
||||
MKFSELF_NPDRM = $(CELL_HOST_PATH)/bin/make_fself_npdrm
|
||||
MKPKG_NPDRM = $(CELL_HOST_PATH)/bin/make_package_npdrm
|
||||
|
||||
# Geohot CFW defines
|
||||
MKSELF_GEOHOT = make_self_npdrm
|
||||
MKPKG_PSLIGHT = buildtools/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++
|
||||
|
||||
EBOOT_LAUNCHER_DIR = eboot-launcher
|
||||
|
||||
PPU_SRCS = $(EBOOT_LAUNCHER_DIR)/main.cpp
|
||||
|
||||
PPU_TARGET = EBOOT.ELF
|
||||
|
||||
PPU_CFLAGS += -I. -DUSE_FILE32API -Dunix -DPSGL -O2 -DCORRECT_VRAM_READS -DRIGHTSHIFT_IS_SAR -DSN_TARGET_PS3 -DNDEBUG=1 -DWORDS_BIGENDIAN -DBLARGG_BIG_ENDIAN=1 -DNO_LOGGER -D__POWERPC__ -D__ppc__ -g
|
||||
PPU_CXXFLAGS += -I./src/ -I./src/snes9x/ -DZLIB -DUNZIP_SUPPORT -DJMA_SUPPORT -DPSGL -O2 -DCORRECT_VRAM_READS -DRIGHTSHIFT_IS_SAR -DNO_LOGGER -DSN_TARGET_PS3 -DNDEBUG=1 -DWORDS_BIGENDIAN -DBLARGG_BIG_ENDIAN=1 -D__POWERPC__ -D__ppc__
|
||||
|
||||
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 += -lfont_stub -lfontFT_stub -lfreetype_stub -lpthread -lmixer -lm -lmstreamSPURSMP3 -ladec_stub -laudio_stub -lnet_stub -lnetctl_stub -lpngdec_stub -lm -ldbgfont_gcm -lgcm_cmd -lgcm_sys_stub -lio_stub -lsysmodule_stub -lsysutil_stub -lfs_stub -lhttp_util_stub -lspurs_stub -ljpgdec_stub -lhttp_stub -lsysutil_music_export_stub -lsysutil_photo_export_stub -lsysutil_video_export_stub -lrtc_stub \
|
||||
|
||||
include $(CELL_MK_DIR)/sdk.target.mk
|
||||
|
||||
.PHONY: pkg
|
||||
#standard pkg packaging
|
||||
pkg: $(PPU_TARGET)
|
||||
$(MKSELF_GEOHOT) EBOOT.ELF pkg/USRDIR/EBOOT.BIN SNES900000
|
||||
|
||||
|
||||
#massively reduced filesize using MKSELF_GEOHOT - use this for normal jailbreak builds
|
||||
.PHONY: pkg-signed
|
||||
pkg-signed: $(PPU_TARGET)
|
||||
$(MKSELF_GEOHOT) EBOOT.ELF pkg/USRDIR/EBOOT.BIN SNES900000
|
||||
|
||||
#use this to create a PKG for use with Geohot CFW 3.55
|
||||
.PHONY: pkg-signed-cfw
|
||||
pkg-signed-cfw:
|
||||
$(MKSELF_GEOHOT) EBOOT.ELF pkg/USRDIR/EBOOT.BIN SNES900000
|
314
Makefile-profile
Normal file
@ -0,0 +1,314 @@
|
||||
# set build tools
|
||||
CELL_BUILD_TOOLS = GCC
|
||||
|
||||
ifeq ($(shell uname), Linux)
|
||||
CELL_HOST_PATH = $(CELL_SDK)/host-linux
|
||||
else
|
||||
CELL_HOST_PATH = $(CELL_SDK)/host-win32
|
||||
endif
|
||||
|
||||
|
||||
# CELL_GPU_TYPE (currently RSX is only one option)
|
||||
CELL_GPU_TYPE = RSX
|
||||
|
||||
# CELL_PSGL_VERSION is debug, dpm or opt
|
||||
CELL_PSGL_VERSION = opt
|
||||
|
||||
|
||||
# set path to important executables
|
||||
MKFSELF_NPDRM = $(CELL_HOST_PATH)/bin/make_fself_npdrm
|
||||
MKFSELF = $(CELL_HOST_PATH)/bin/make_fself
|
||||
MKPKG_NPDRM = $(CELL_HOST_PATH)/bin/make_package_npdrm
|
||||
STRIP = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-strip
|
||||
COPY = cp
|
||||
C = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-gcc
|
||||
CC = $(CELL_HOST_PATH)/ppu/bin/ppu-lv2-g++
|
||||
|
||||
# set path to all relevants directories
|
||||
SRC_DIR = src
|
||||
CELL_FRAMEWORK_DIR = src/cellframework
|
||||
CELL_FRAMEWORK2_DIR = src/cellframework2
|
||||
SNES9X_API_DIR = src/snes9x
|
||||
UTIL_DIR = utils
|
||||
BUILD_DIR = objs
|
||||
|
||||
|
||||
# build list of source directories
|
||||
SNES9X_SRC_DIR := $(SNES9X_API_DIR)/ $(SNES9X_API_DIR)/unzip $(SNES9X_API_DIR)/apu $(SNES9X_API_DIR)/jma
|
||||
|
||||
PS3_SRC_DIR := $(CELL_FRAMEWORK_DIR)/graphics $(CELL_FRAMEWORK2_DIR)/input $(CELL_FRAMEWORK2_DIR)/audio \
|
||||
$(CELL_FRAMEWORK_DIR)/threads $(CELL_FRAMEWORK_DIR)/logger $(CELL_FRAMEWORK_DIR)/network \
|
||||
$(CELL_FRAMEWORK_DIR)/fileio \
|
||||
$(CELL_FRAMEWORK_DIR)/utility \
|
||||
$(SRC_DIR)/ $(SRC_DIR)/conf
|
||||
|
||||
UTIL_SRC_DIR := $(UTIL_DIR)/ $(UTIL_DIR)/zlib $(UTIL_DIR)/zlib/contrib/minizip
|
||||
|
||||
# build src lists and object file lists
|
||||
SNES9X_CPPSRCS = $(SNES9X_API_DIR)/cpu.cpp \
|
||||
$(SNES9X_API_DIR)/cpuexec.cpp \
|
||||
$(SNES9X_API_DIR)/cpuops.cpp \
|
||||
$(SNES9X_API_DIR)/srtc.cpp \
|
||||
$(SNES9X_API_DIR)/dma.cpp \
|
||||
$(SNES9X_API_DIR)/memmap.cpp \
|
||||
$(SNES9X_API_DIR)/sa1.cpp \
|
||||
$(SNES9X_API_DIR)/sa1cpu.cpp \
|
||||
$(SNES9X_API_DIR)/apu/apu.cpp \
|
||||
$(SNES9X_API_DIR)/apu/SNES_SPC.cpp \
|
||||
$(SNES9X_API_DIR)/apu/SNES_SPC_misc.cpp \
|
||||
$(SNES9X_API_DIR)/apu/SNES_SPC_state.cpp \
|
||||
$(SNES9X_API_DIR)/apu/SPC_DSP.cpp \
|
||||
$(SNES9X_API_DIR)/apu/SPC_Filter.cpp \
|
||||
$(SNES9X_API_DIR)/fxdbg.cpp \
|
||||
$(SNES9X_API_DIR)/fxemu.cpp \
|
||||
$(SNES9X_API_DIR)/fxinst.cpp \
|
||||
$(SNES9X_API_DIR)/gfx.cpp \
|
||||
$(SNES9X_API_DIR)/ppu.cpp \
|
||||
$(foreach dir,$(SNES9X_API_DIR)/jma/,$(wildcard $(dir)/*.cpp)) \
|
||||
$(SNES9X_API_DIR)/bsx.cpp \
|
||||
$(SNES9X_API_DIR)/c4.cpp \
|
||||
$(SNES9X_API_DIR)/c4emu.cpp \
|
||||
$(SNES9X_API_DIR)/cheats.cpp \
|
||||
$(SNES9X_API_DIR)/cheats2.cpp \
|
||||
$(SNES9X_API_DIR)/clip.cpp \
|
||||
$(SNES9X_API_DIR)/conffile.cpp \
|
||||
$(SNES9X_API_DIR)/controls.cpp \
|
||||
$(SNES9X_API_DIR)/crosshairs.cpp \
|
||||
$(SNES9X_API_DIR)/debug.cpp \
|
||||
$(SNES9X_API_DIR)/dsp.cpp \
|
||||
$(SNES9X_API_DIR)/dsp1.cpp \
|
||||
$(SNES9X_API_DIR)/dsp2.cpp \
|
||||
$(SNES9X_API_DIR)/dsp3.cpp \
|
||||
$(SNES9X_API_DIR)/dsp4.cpp \
|
||||
$(SNES9X_API_DIR)/globals.cpp \
|
||||
$(SNES9X_API_DIR)/loadzip.cpp \
|
||||
$(SNES9X_API_DIR)/logger.cpp \
|
||||
$(SNES9X_API_DIR)/movie.cpp \
|
||||
$(SNES9X_API_DIR)/netplay.cpp \
|
||||
$(SNES9X_API_DIR)/obc1.cpp \
|
||||
$(SNES9X_API_DIR)/reader.cpp \
|
||||
$(SNES9X_API_DIR)/screenshot.cpp \
|
||||
$(SNES9X_API_DIR)/sdd1.cpp \
|
||||
$(SNES9X_API_DIR)/sdd1emu.cpp \
|
||||
$(SNES9X_API_DIR)/server.cpp \
|
||||
$(SNES9X_API_DIR)/seta.cpp \
|
||||
$(SNES9X_API_DIR)/seta010.cpp \
|
||||
$(SNES9X_API_DIR)/seta011.cpp \
|
||||
$(SNES9X_API_DIR)/seta018.cpp \
|
||||
$(SNES9X_API_DIR)/snapshot.cpp \
|
||||
$(SNES9X_API_DIR)/snes9x.cpp \
|
||||
$(SNES9X_API_DIR)/spc7110.cpp \
|
||||
$(SNES9X_API_DIR)/tile.cpp
|
||||
#SNES9X_CPPSRCS = $(foreach dir,$(SNES9X_SRC_DIR),$(wildcard $(dir)/*.cpp))
|
||||
SNES9X_CPPOBJS = $(SNES9X_CPPSRCS:.cpp=.ppu.o)
|
||||
SNES9X_CSRCS = $(foreach dir,$(SNES9X_SRC_DIR),$(wildcard $(dir)/*.c))
|
||||
SNES9X_COBJS = $(SNES9X_CSRCS:.c=.ppu.o)
|
||||
|
||||
PS3_CPPSRCS = $(foreach dir,$(PS3_SRC_DIR),$(wildcard $(dir)/*.cpp))
|
||||
PS3_CPPOBJS = $(PS3_CPPSRCS:.cpp=.ppu.o)
|
||||
PS3_CSRCS = $(foreach dir,$(PS3_SRC_DIR),$(wildcard $(dir)/*.c))
|
||||
PS3_COBJS = $(PS3_CSRCS:.c=.ppu.o)
|
||||
|
||||
UTIL_CPPSRCS = $(foreach dir,$(UTIL_SRC_DIR),$(wildcard $(dir)/*.cpp))
|
||||
UTIL_CPPOBJS = $(UTIL_CPPSRCS:.cpp=.ppu.o)
|
||||
#UTIL_CSRCS = $(foreach dir,$(UTIL_SRC_DIR),$(wildcard $(dir)/*.c))
|
||||
UTIL_CSRCS += $(UTIL_DIR)/zlib/adler32.c \
|
||||
$(UTIL_DIR)/zlib/compress.c \
|
||||
$(UTIL_DIR)/zlib/crc32.c \
|
||||
$(UTIL_DIR)/zlib/deflate.c \
|
||||
$(UTIL_DIR)/zlib/gzclose.c \
|
||||
$(UTIL_DIR)/zlib/gzlib.c \
|
||||
$(UTIL_DIR)/zlib/gzread.c \
|
||||
$(UTIL_DIR)/zlib/gzwrite.c \
|
||||
$(UTIL_DIR)/zlib/infback.c \
|
||||
$(UTIL_DIR)/zlib/inffast.c \
|
||||
$(UTIL_DIR)/zlib/inflate.c \
|
||||
$(UTIL_DIR)/zlib/inftrees.c \
|
||||
$(UTIL_DIR)/zlib/trees.c \
|
||||
$(UTIL_DIR)/zlib/uncompr.c \
|
||||
$(UTIL_DIR)/zlib/zutil.c
|
||||
UTIL_COBJS = $(UTIL_CSRCS:.c=.ppu.o)
|
||||
|
||||
PPU_CPPOBJS = $(SNES9X_CPPOBJS:%=$(BUILD_DIR)/%) $(PS3_CPPOBJS:%=$(BUILD_DIR)/%) $(UTIL_CPPOBJS:%=$(BUILD_DIR)/%)
|
||||
PPU_COBJS = $(SNES9X_COBJS:%=$(BUILD_DIR)/%) $(PS3_COBJS:%=$(BUILD_DIR)/%) $(UTIL_COBJS:%=$(BUILD_DIR)/%)
|
||||
|
||||
# Output file
|
||||
PPU_TARGET = snes9x.ppu.elf
|
||||
|
||||
|
||||
# default flags from sony
|
||||
PPU_CXXFLAGS = -std=c++98 -W -Wall -Wuninitialized -Wcomment -Wchar-subscripts \
|
||||
-Wdeprecated-declarations -Wendif-labels -Wformat=2 -Wformat-extra-args \
|
||||
-Wimplicit -Wimport -Winline -Wmissing-braces -Wparentheses -Wpointer-arith \
|
||||
-Wredundant-decls -Wreturn-type -Wshadow -Wsign-compare -Wswitch \
|
||||
-Wunknown-pragmas -Wunused -Wwrite-strings
|
||||
PPU_CFLAGS = -W -Wall -Wuninitialized -Wcomment -Wchar-subscripts \
|
||||
-Wdeprecated-declarations -Wendif-labels -Wformat=2 -Wformat-extra-args \
|
||||
-Wimplicit -Wimport -Winline -Wmissing-braces -Wparentheses -Wpointer-arith \
|
||||
-Wredundant-decls -Wreturn-type -Wshadow -Wsign-compare -Wswitch \
|
||||
-Wunknown-pragmas -Wunused -Wwrite-strings
|
||||
|
||||
# PLATFORM
|
||||
PPU_CXXFLAGS += -D__CELLOS_LV2__
|
||||
PPU_CFLAGS += -D__CELLOS_LV2__
|
||||
|
||||
|
||||
# include flags
|
||||
PPU_CXXFLAGS += -I. -I$(SNES9X_API_DIR) -I./utils/ -I./utils/zlib
|
||||
PPU_CFLAGS += -I. -I$(SNES9X_API_DIR) -I./utils/ -I./utils/zlib
|
||||
|
||||
# compiler optimizations
|
||||
PPU_CXXFLAGS += -O3 \
|
||||
-ffast-math \
|
||||
-finline-functions \
|
||||
-funit-at-a-time \
|
||||
--param inline-unit-growth=200 \
|
||||
--param large-function-growth=1000 \
|
||||
--param max-inline-insns-single=450
|
||||
|
||||
PPU_CFLAGS += -O3 \
|
||||
-ffast-math \
|
||||
-finline-functions \
|
||||
-funit-at-a-time \
|
||||
--param inline-unit-growth=200 \
|
||||
--param large-function-growth=1000 \
|
||||
--param max-inline-insns-single=450
|
||||
|
||||
# port must define
|
||||
PPU_CXXFLAGS += -DPSGL -DCORRECT_VRAM_READS -DRIGHTSHIFT_IS_SAR -DUNZIP_SUPPORT -DJMA_SUPPORT -DZLIB
|
||||
PPU_CFLAGS += -DPSGL -DCORRECT_VRAM_READS -DRIGHTSHIFT_IS_SAR -Dunix -DUSE_FILE32API -DUNZIP_SUPPORT -DJMA_SUPPORT
|
||||
|
||||
# DISABLE DEBUG, to enabled add -g
|
||||
PPU_CXXFLAGS +=
|
||||
PPU_CFLAGS +=
|
||||
|
||||
|
||||
# enable debug netlogger
|
||||
PPU_CXXFLAGS += -DCELL_DEBUG -DPS3_DEBUG_IP=\"192.168.1.7\" -DPS3_DEBUG_PORT=9002
|
||||
PPU_CFLAGS += -DCELL_DEBUG -DPS3_DEBUG_IP=\"192.168.1.7\" -DPS3_DEBUG_PORT=9002
|
||||
|
||||
|
||||
# enable screen debugger
|
||||
#PPU_CXXFLAGS += -DEMUDEBUG -DEMU_DBG_DELAY=500000
|
||||
#PPU_CFLAGS += -DEMUDEBUG -DEMU_DBG_DELAY=500000
|
||||
|
||||
|
||||
# enable telnet control console
|
||||
#PPU_CSTDFLAGS += -DCONTROL_CONSOLE -D__PPU__
|
||||
#PPU_CSTDFLAGS += -DCONSOLE_USE_NETWORK
|
||||
#PPU_CXXSTDFLAGS += -DCONTROL_CONSOLE -D__PPU__
|
||||
#PPU_CXXSTDFLAGS += -DCONSOLE_USE_NETWORK
|
||||
|
||||
|
||||
# default SNES9x file libs
|
||||
PPU_CXXSNES9XFLAGS = $(PPU_CXXFLAGS)
|
||||
PPU_CSNES9XFLAGS = $(PPU_CFLAGS)
|
||||
|
||||
|
||||
# libs, order matters!
|
||||
PPU_LDLIBS += -L. -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/opt -ldbgfont -lPSGL -lPSGLcgc -lcgc \
|
||||
-lgcm_cmd -lgcm_sys_stub -lresc_stub -lm -lio_stub -lfs_stub -lsysutil_stub \
|
||||
-lcontrol_console_ppu -lsysmodule_stub -laudio_stub -lpthread -lnet_stub -lnetctl_stub
|
||||
|
||||
|
||||
# RULE: ALL
|
||||
all: $(PPU_TARGET) $(PPU_TARGET:%.elf=%.self)
|
||||
|
||||
|
||||
# RULE: All cpp files, can differentiate for SNES9x dir
|
||||
$(BUILD_DIR)/%.ppu.o: %.cpp
|
||||
@mkdir -p $(@D)
|
||||
$(if $(findstring $@,$(SNES9X_CPPOBJS:%=$(BUILD_DIR)/%)),\
|
||||
$(CC) $(PPU_CXXSNES9XFLAGS) -o $@ -c $<,\
|
||||
$(CC) $(PPU_CXXFLAGS) -o $@ -c $<)
|
||||
|
||||
|
||||
# RULE: All c files, can differentiate for SNES9x dir
|
||||
$(BUILD_DIR)/%.ppu.o: %.c
|
||||
@mkdir -p $(@D)
|
||||
$(if $(findstring $@,$(SNES9X_COBJS:%=$(BUILD_DIR)/%)),\
|
||||
ppu-lv2-gcc $(PPU_CSNES9XFLAGS) -o $@ -c $<,\
|
||||
ppu-lv2-gcc $(PPU_CFLAGS) -o $@ -c $<)
|
||||
|
||||
|
||||
# RULE: build the elf file
|
||||
$(PPU_TARGET): $(PPU_CPPOBJS) $(PPU_COBJS)
|
||||
$(CC) $(PPU_CXXFLAGS) $(PPU_LDLIBS) -o $(PPU_TARGET) $(PPU_CPPOBJS) $(PPU_COBJS)
|
||||
|
||||
|
||||
# RULE: build the self file
|
||||
$(PPU_TARGET:%.elf=%.self): $(PPU_TARGET)
|
||||
$(MKFSELF) $(PPU_TARGET) $(PPU_TARGET:%.elf=%.self)
|
||||
|
||||
|
||||
# RULE: generates the compiler and linker flags for profile-arcs
|
||||
genProfile: set_genProfile_flags all
|
||||
|
||||
set_genProfile_flags: $(BUILD_DIR)/$(CELL_FRAMEWORK_DIR)/network-stdio/net_stdio.ppu.o
|
||||
touch ./src/main.cpp
|
||||
$(eval PS3_SRC_DIR += $(CELL_FRAMEWORK_DIR)/network-stdio)
|
||||
$(eval PPU_CXXFLAGS += -DPS3_PROFILING -DPS3_PROFILING_IP=\"192.168.1.7\" -DPS3_PROFILING_PORT=9001)
|
||||
$(eval PPU_CFLAGS += -DPS3_PROFILING -DPS3_PROFILING_IP=\"192.168.1.7\" -DPS3_PROFILING_PORT=9001)
|
||||
$(eval PPU_CXXSNES9XFLAGS = $(PPU_CXXFLAGS) -fprofile-generate -fprofile-arcs)
|
||||
$(eval PPU_CSNES9XFLAGS = $(PPU_CFLAGS) -fprofile-generate -fprofile-arcs)
|
||||
$(eval PPU_LDLIBS += -lgcov -fprofile-generate)
|
||||
$(eval PPU_LDLIBS += -Wl,-wrap,fopen -Wl,-wrap,fclose -Wl,-wrap,fwrite -Wl,-wrap,fread -Wl,-wrap,fseek -Wl,-wrap,ftell -Wl,-wrap,fflush -Wl,-wrap,rewind -Wl,-wrap,fgetpos -Wl,-wrap,fsetpos -Wl,-wrap,setbuf -Wl,-wrap,setvbuf -Wl,-wrap,ungetc -Wl,-wrap,feof)
|
||||
|
||||
|
||||
# RULE: use a generated profile (gcda files)
|
||||
useProfile: set_useProfile_flags all
|
||||
|
||||
set_useProfile_flags:
|
||||
touch ./src/main.cpp
|
||||
$(eval PPU_CXXSNES9XFLAGS = $(PPU_CXXFLAGS) -fprofile-use)
|
||||
$(eval PPU_CSNES9XFLAGS = $(PPU_CFLAGS) -fprofile-use)
|
||||
$(eval PPU_LDLIBS += -fprofile-use)
|
||||
|
||||
|
||||
# RULE: build the package
|
||||
pkg: $(PPU_TARGET)
|
||||
$(STRIP) $(PPU_TARGET)
|
||||
$(MKFSELF_NPDRM) $(PPU_TARGET) pkg/USRDIR/EBOOT.BIN
|
||||
$(COPY) -r ./src/cellframework/extra/shaders pkg/USRDIR/
|
||||
$(MKPKG_NPDRM) pkg/package.conf pkg
|
||||
|
||||
|
||||
# RULE: testing...
|
||||
echo:
|
||||
echo $(PPU_CPPOBJS)
|
||||
echo $(BUILD_DIR)/$(CELL_FRAMEWORK_DIR)/network-stdio/net_stdio.ppu.o
|
||||
|
||||
|
||||
# RULE - force, for empty dependency
|
||||
force: ;
|
||||
|
||||
|
||||
# RULE - clean SNES9x or ps3 or utils or all
|
||||
clean_snes9x:
|
||||
@rm $(SNES9X_CPPOBJS:%=$(BUILD_DIR)/%) -f
|
||||
@rm $(SNES9X_CPPOBJS:%.o=$(BUILD_DIR)/%.d) -f
|
||||
@rm $(SNES9X_COBJS:%=$(BUILD_DIR)/%) -f
|
||||
@rm $(SNES9X_COBJS:%.o=$(BUILD_DIR)/%.d) -f
|
||||
|
||||
clean_ps3:
|
||||
@rm $(PS3_CPPOBJS:%=$(BUILD_DIR)/%) -f
|
||||
@rm $(PS3_CPPOBJS:%.o=$(BUILD_DIR)/%.d) -f
|
||||
@rm $(PS3_COBJS:%=$(BUILD_DIR)/%) -f
|
||||
@rm $(PS3_COBJS:%.o=$(BUILD_DIR)/%.d) -f
|
||||
@rm $(BUILD_DIR)/$(CELL_FRAMEWORK_DIR)/network-stdio/net_stdio.ppu.o -f
|
||||
|
||||
clean_util:
|
||||
@rm $(UTIL_CPPOBJS:%=$(BUILD_DIR)/%) -f
|
||||
@rm $(UTIL_CPPOBJS:%.o=$(BUILD_DIR)/%.d) -f
|
||||
@rm $(UTIL_COBJS:%=$(BUILD_DIR)/%) -f
|
||||
@rm $(UTIL_COBJS:%.o=$(BUILD_DIR)/%.d) -f
|
||||
|
||||
clean: clean_snes9x clean_ps3 clean_util
|
||||
@rm $(PPU_TARGET) $(PPU_TARGET:%.elf=%.self) -f
|
||||
|
||||
.PHONY: pkg
|
||||
pkg: $(PPU_TARGET)
|
||||
$(STRIP) $(PPU_TARGET)
|
||||
$(MKFSELF_NPDRM) $(PPU_TARGET) pkg/USRDIR/EBOOT.BIN
|
||||
$(COPY) -r src/cellframework/extra/shaders pkg/USRDIR/
|
||||
$(MKPKG_NPDRM) pkg/package.conf pkg
|
623
PS3-SNES9x-CHANGELOG.txt
Normal file
@ -0,0 +1,623 @@
|
||||
*******************************************************************************
|
||||
SNES9x PS3
|
||||
CHANGELOG
|
||||
*******************************************************************************
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.9 (12-04-2011)
|
||||
===============================================================================
|
||||
* Custom Soundtrack support - select a song/album/playlist from the XMB
|
||||
Music category - music can be played both in-game and from within the menu.
|
||||
|
||||
* Added USB/Bluetooth headset support - sound gets output through the
|
||||
headset.
|
||||
|
||||
* Fixed Super Mario RPG level-up freeze.
|
||||
|
||||
* Fixed Super Mario World 2: Yoshi's Island save file selection screen graphical
|
||||
glitch.
|
||||
|
||||
* Some filebrowser fixes
|
||||
|
||||
* Added 5x scale option.
|
||||
|
||||
* Updated Maister Pong - now with sound effects, scoring, two-player support,
|
||||
nice gameplay mechanics, etc.
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.8 (03-04-2011)
|
||||
===============================================================================
|
||||
* Very big performance and lag reduction optimizations. The previous builds
|
||||
were indeed very laggy - this should be a very big improvement on that front.
|
||||
|
||||
* You can now use two shaders at once - we call this 'Custom Scaling/ Dual
|
||||
Shader' mode. A scaling factor (from 1 to 4x) can be specified.
|
||||
|
||||
Some great graphical effects can be achieved by combining shaders.
|
||||
|
||||
* Shader presets have been added. Shader presets are configuration files that
|
||||
automatically configure the settings for 'Shader 1', 'Shader 2', 'Hardware
|
||||
Filtering Shader 1', 'Hardware Filtering Shader 2', 'Scaling Factor' and
|
||||
'Overscan'. You can create your own shader presets - they are just
|
||||
plain-text files stored in USRDIR/presets.
|
||||
|
||||
* Controllers can now be individually configured - you can specifically
|
||||
configure the controls for a controller connected to a specific port/
|
||||
number.
|
||||
|
||||
* Cheat input has been made less buggy. With the 'New' control scheme -
|
||||
L2 + Analog Stick Right Down will still input cheats with the OSK, but
|
||||
it will add a generic label (simply the cheatcode itself as a label)
|
||||
until you rename this generic label by triggering the action 'Input
|
||||
Cheatlabel'. The 'New' control scheme has this hooked up to 'L2 + R2 +
|
||||
Analog Stick Right - Down'. This can of course be reconfigured to any
|
||||
button / button-combo you see fit.
|
||||
|
||||
* Fixed interlaced games like Rise Of The Robots - were displaying
|
||||
glitched graphics before in version 4.4.7.
|
||||
|
||||
* Added a homebrew SNES game by Themaister. Game logic is semi-hooked
|
||||
up - paddle works, ball bounces off the paddle, just scoring has to
|
||||
be added. Anyway, this has mostly been a 3-day exercise in SNES ASM -
|
||||
there will be a more useful/fun homebrew game in the future. This is
|
||||
just for illustrative purposes.
|
||||
|
||||
* Added some shader variations and some new shaders - HQ4x, BR4x -
|
||||
courtesy of Jacaraca.
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.7 (13-03-2011)
|
||||
===============================================================================
|
||||
- Added new shaders (waterpaint-normalcontrast, waterpaint-normalcontrast-scanline,
|
||||
waterpaint-highcontrast, waterpaint-highcontrast-scanline, crt-highgamma)
|
||||
- Optimized crt, crt-highgamma shaders - both run now at 60fps at 1920x1080.
|
||||
- Reduced lag.
|
||||
- Fixed Turbo Mode toggling - works the same now as in 4.4.4.
|
||||
- Fixed RSound bug with Windows OSes.
|
||||
- Fixed L2 button mapping issue.
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.6 (16-02-2011)
|
||||
===============================================================================
|
||||
- HD version and Normal version merged into one - there are now HD shaders that
|
||||
do the same as the previous HD version.
|
||||
* HD shaders (which upscale the resolution to 512x448) instead of hacked
|
||||
HD version. '4xSoft-HD' is currently the best out of the HD shaders - more to
|
||||
come.
|
||||
* The HD version in version 4.4.5 ran in interlaced mode - with the HD
|
||||
shaders, you can run in either progressive or interlaced mode.
|
||||
- Fixed PAL50/PAL60 automatic activation in 576i/p mode.
|
||||
- Fixed Rise Of The Robots interlacing issues - other games which use
|
||||
interlaced mode also corrected.
|
||||
- Fixed Multiplayer controls - only player 1 worked.
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.5 (14-02-2010)
|
||||
===============================================================================
|
||||
- New HD Version - every game runs at the SNES' high-resolution mode (512x448
|
||||
interlaced mode). Try this with the right shader on (4xSoft) and this can make
|
||||
the games look beautiful. Both progressive (1080p/720p/480p/576p) and interlaced
|
||||
modes (480i/576i/1080i) work with this - try interlaced for best results.
|
||||
|
||||
4xSoft combined with this HD version also beautifies the pseudo hi-res
|
||||
transparent background layers in Kirby's Dreamland 3.
|
||||
- Triple Buffering option added - enabled by default. Faster graphics/shader
|
||||
performance with triple buffering turned on - some potential input lag with
|
||||
triple buffering on - turn it off in case you experience problems of this
|
||||
nature.
|
||||
- USB/Bluetooth mouse can be used now for Mouse/Super Scope games.
|
||||
- Primal Rage works again.
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.4 (19-01-2010)
|
||||
===============================================================================
|
||||
- FIXED: (CHRONO TRIGGER SCREEN HEIGHT JUMPING BUG)
|
||||
===============================================================================
|
||||
Chrono Trigger would jump from 256x224 to 256x239 for one odd frame when
|
||||
transitioning from normal mode to battle mode - this caused an undesirable
|
||||
screen hiccup to occur everytime. This issue has been fixed.
|
||||
|
||||
===============================================================================
|
||||
- FIXED: Player 2 - Buttons X/Y didn't work
|
||||
===============================================================================
|
||||
This bug was introduced in v4.4.3 due to an improper macro. It has now been
|
||||
fixed as of v4.4.4.
|
||||
|
||||
===============================================================================
|
||||
- FIXED: Loading a ROM with a cheatfile loaded and then loading another ROM
|
||||
with no cheatfile will not clear out the previous game's cheats
|
||||
===============================================================================
|
||||
This bug was introduced in v4.4.0, and has now been fixed as of v4.4.4. Also
|
||||
note that games which do not have a cheatfile will create a new cheatfile
|
||||
automatically.
|
||||
|
||||
===============================================================================
|
||||
- FIXED: Super Scope controls auto-centered when let go of thumbstick
|
||||
- ADDED: Better Super Scope controls
|
||||
===============================================================================
|
||||
Previously in v4.4.3, the Super Scope crosshair would center back to the middle
|
||||
of the screen as soon as you let go of the thumbstick on the left analog stick.
|
||||
Now it controls much more closely to the mouse. Note that there might be an
|
||||
option to toggle the Super Scope controls in the future (to either auto-center
|
||||
when let go of the thumbstick or let the cursor stay at the current position).
|
||||
|
||||
===============================================================================
|
||||
- FIXED: Some games were hooked up with patchy controls (Doom)
|
||||
- ADDED: Accessory Autodetection
|
||||
===============================================================================
|
||||
The accessory autodetection in v4.4.2/4.4.3 left some things to be desired.
|
||||
A new setting has been added to the SNES9x Settings screen - 'Accessory Auto-
|
||||
detection'.
|
||||
|
||||
SNES9x PS3 auto-detects most games that feature support for these peripherals.
|
||||
This setting will control how SNES9x PS3 will deal with these games when it
|
||||
detects them.
|
||||
|
||||
CONFIRM - When detecting a Mouse/Scope/Multitap-compatible game, a dialog
|
||||
screen is presented to the user asking him/her if the accessory
|
||||
should be enabled. If you select 'No', normal 2 joypad controls
|
||||
will be used instead.
|
||||
ON - Games which support Mouse/Scope/Multitap will be automatically
|
||||
detected and the accessory will be automatically enabled without
|
||||
any input from the user.
|
||||
OFF - Accessories will not be detected or enabled - standard 2 joypad
|
||||
controls for all games.
|
||||
|
||||
===============================================================================
|
||||
- ADDED: Control Schemes
|
||||
===============================================================================
|
||||
There are now three [Control Schemes] - 'Default', 'New', and 'Custom'.
|
||||
|
||||
DEFAULT - Controls are the same as they were before.
|
||||
|
||||
NEW - A new control scheme. See below:
|
||||
|
||||
R3 + L3 - [Exit to Menu] - go back to the ROM Browser
|
||||
menu.
|
||||
|
||||
Right analog stick - Up - SNES9x pause (supersedes regular SNES pause).
|
||||
Right analog stick - Left - Decrement fastforward speed by one (-1).
|
||||
Right analog stick - Right - Increment fastforward speed by one (+1).
|
||||
Right analog stick - Down - Toggle [Fastforwarding] on/off.
|
||||
|
||||
Right analog stick - Left + L2 - Decrement cheat position by one (-1).
|
||||
Right analog stick - Right + L2 - Increment cheat position by one (+1).
|
||||
Right analog stick - Up + L2 - Toggle the currently selected cheat on/off.
|
||||
Right analog stick - Down + L2 - Input a cheat with an on-screen keyboard.
|
||||
|
||||
Right analog stick - Left + R2 - Decrement save state slot by one (-1).
|
||||
Right analog stick - Right + R2 - Increment save state slot by one (+1).
|
||||
Right analog stick - Up + R2 - Load from currently selected save state slot.
|
||||
Right analog stick - Down + R2 - Save to currently selected save state slot.
|
||||
R2 + R3 - Toggle [SRAM Write Protection] on/off.
|
||||
|
||||
L2 + R3 - Toggle [Record Movie] on/off.
|
||||
L2 + L3 - Load Movie
|
||||
|
||||
CUSTOM - Custom control scheme. All buttons/button combos can be
|
||||
customized.
|
||||
|
||||
===============================================================================
|
||||
- ADDED: Savestate SRAM Overwrite Protect
|
||||
===============================================================================
|
||||
Implemented by request - see Issue 8: Loading a save state also load the
|
||||
associated save ram file and write it to disk right away.
|
||||
(URL: https://code.google.com/p/snes9x-ps3/issues/detail?id=8&can=1)
|
||||
|
||||
Normally, when SNES9x loads a savestate, the SRAM contents are automatically
|
||||
overwritten. The ugly side-effect of this is that this can unknowingly
|
||||
delete your normal saved game progress.
|
||||
|
||||
ON - SNES9x will write-protect SRAM - this means that if you load a save-
|
||||
state, it will not overwrite the SRAM save(s). However, SRAM is not
|
||||
saved at all in this mode.
|
||||
OFF - SRAM is writable - this means that if you load a savestate, it will
|
||||
overwrite the SRAM save(s).
|
||||
|
||||
NOTE: This option can be toggled in-game with the 'New' control scheme by
|
||||
pressing button combo [R2 + R3].
|
||||
|
||||
===============================================================================
|
||||
- ADDED: Cheat Code Input In-game with Onscreen Keyboard
|
||||
===============================================================================
|
||||
Cheatcodes can now be inserted with an onscreen keyboard in-game. A new
|
||||
action has been added called 'Cheat Input'.
|
||||
|
||||
Cheatcodes that you add will be saved to your cheatfile. Currently, the cheat
|
||||
code will be added in order.
|
||||
|
||||
NOTE: This option can be toggled in-game with the 'New' control scheme by
|
||||
pressing button combo [L2 + Analog Stick Right - Down].
|
||||
|
||||
NOTE: There is still a bug that happens after inserting 15/16 cheat codes
|
||||
in a row.
|
||||
|
||||
When this bug happens, you will no longer be presented with the option to
|
||||
input a label after correctly inputting a cheat. Instead, the label will be
|
||||
the cheat code itself. This is a memory shortage bug that we hope to fix soon.
|
||||
|
||||
===============================================================================
|
||||
- ADDED: Resolution saving
|
||||
===============================================================================
|
||||
Implemented by request - see Issue 18: Screen resolution does not save upon
|
||||
exit
|
||||
(URL: https://code.google.com/p/snes9x-ps3/issues/detail?id=18&can=1)
|
||||
|
||||
The resolution you had previously played in will now be automatically selected
|
||||
when you start SNES9x the next time.
|
||||
|
||||
There are also sane fallbacks. If SNES9x saved the resolution at 1080p and the
|
||||
next time you want to play SNES9x you happen to have your PS3 connected to a
|
||||
screen that doesn't support 1080p - it will fall back to a lower resolution
|
||||
that your TV does support.
|
||||
|
||||
===============================================================================
|
||||
- ADDED: Throttle Mode
|
||||
===============================================================================
|
||||
This is a performance benchmarking feature that might or might not be useful
|
||||
to users. Turn this 'Off', and VSync and audio will be disabled - the game
|
||||
will then run at the maximum amount of frames per second (FPS) that the PS3
|
||||
can manage.
|
||||
|
||||
NOTE: There seems to be a hardware/software cap of 124/125fps that appears to
|
||||
be prevalent even in menus.
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.3 (11-01-2010)
|
||||
===============================================================================
|
||||
- Autodetection of Super Scope/Mouse/Multitap had a bug in it - after you
|
||||
loaded a Super Scope/mouse game and then tried to load a multitap-compatible
|
||||
game, the game would attempt to hook up the Mouse/Scope instead due to an error
|
||||
in a switch/case statement. Fixed this.
|
||||
|
||||
Autodetection now works as expected. Please upgrade to 4.4.3 as soon as possible
|
||||
to avoid inconvenient problems.
|
||||
|
||||
-==============================================================================
|
||||
Build 4.4.2 (09-01-2011) - rev. number ?
|
||||
===============================================================================
|
||||
* Super Scope and SNES Mouse support. The Super Scope and the Mouse are currently
|
||||
mapped to the left analog stick - the controls are -
|
||||
- Circle Button - Scope Toggle Turbo
|
||||
- Cross Button - Scope Cursor Button
|
||||
- Triangle Button - Mouse R Button - Scope Aim Off Screen
|
||||
- Square Button - Mouse L Button -Scope Fire
|
||||
- Start Button - Scope Pause Button
|
||||
* Automatic Super Scope/Mouse support detection (works for most games)
|
||||
* Automatic multitap detection (for most games)
|
||||
* Automatic PAL50/PAL60 switching (for 576p PAL resolution only)
|
||||
* Only shows toggleable resolutions now in the Settings menu that your TV supports.
|
||||
* Fixed Syvalion/R.P.M. Racing/Power Drive (games use 512x448 - flickered
|
||||
like mad before)
|
||||
* Added .GD3 ROM extension.
|
||||
* Added configurable controls - nearly any button/button combo can be
|
||||
configured. All of the configurable settings are saved of course.
|
||||
* Some of the new things you can 'bind' buttons to:
|
||||
- Record movie
|
||||
- Stop movie
|
||||
- Playback movie
|
||||
- Fast forward
|
||||
- Increase fast-forward speed
|
||||
- Decrease fast-forward speed
|
||||
- Reset
|
||||
- Soft Reset
|
||||
- Some more shaders (Lanzcos12/Lanzcos16/SuperScale2x - you've probably seen
|
||||
them already in Genesis Plus/FBA et al - that's because they all use the
|
||||
same shaders from Cellframework.)
|
||||
- Sane parental control defaults (you can use this when parental control is
|
||||
enabled at highest level).
|
||||
- You can set the SRAM path directory now.
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.1 (15-11-2010) - rev. number da152b168e
|
||||
===============================================================================
|
||||
* Added pixel shaders - select them in General Settings.
|
||||
The following pixel shaders have been added:
|
||||
- Stock (Default shader)
|
||||
- 2xSaI
|
||||
- Blur
|
||||
- Curved CRT
|
||||
- HQ2x
|
||||
- Quad interpolation
|
||||
- Scanlines
|
||||
- Sharpen
|
||||
- Super2xSaI
|
||||
- SuperEagle
|
||||
all but SuperEagle, Super2xSaI and Curved CRT run at fullspeed at 1080p 16:9 -
|
||||
the highest resolution. If a shader doesn't run at fullspeed on that
|
||||
resolution, 720p resolution will run it just fine at fullspeed.
|
||||
* PAL60 option works with 1.92 version
|
||||
* Added a 'Force NTSC ROM to PAL' option in SNES9x Settings
|
||||
|
||||
===============================================================================
|
||||
Build 4.4.0 (12-11-2010) - rev. number 0cb00f8c86
|
||||
===============================================================================
|
||||
* PAL issues are fixed at all resolutions - ghosting is gone
|
||||
* It's now possible to run NTSC ROMs and PAL ROMs alike correctly at 576p PAL
|
||||
mode. When the setting 'PAL60' is set to ON, a trick will be applied to get
|
||||
NTSC ROMs to run correctly at 50Hz mode. If set to OFF, it will run PAL ROMs
|
||||
correctly. Even though PAL ROMs will play normally now at 480p/720p/1080p,
|
||||
576p still seems to run PAL ROMs slightly better - but it's probably
|
||||
unnoticeable to the user.
|
||||
* Cheatcode files can now be loaded and selected/enabled ingame. Note that
|
||||
all zSNES and SNES9x cheatcode files are supported - everything with the .CHT
|
||||
extension. You can also set a Cheatfile directory. If you don't set a
|
||||
Cheatfile directory, the default will be USRDIR.
|
||||
|
||||
Cheatfiles must have the same filename as the ROM. Here is how selecting
|
||||
and enabling cheats works in-game:
|
||||
|
||||
Right analog stick - Left + L2 - Move cheat position back by one (-1)
|
||||
Right analog stick - Right + L2 - Move cheat position forwards by one (+1)
|
||||
Right analog stick - Up - Enable the currently selected cheat
|
||||
Right analog stick - Down - Disable the currently selected cheat
|
||||
|
||||
Here are two links with some quite useful cheatfiles:
|
||||
|
||||
https://code.google.com/p/snes9x-gx/downloads/detail?name=Snes9x%20GX%20Cheat%20Files.zip&can=2&q=
|
||||
|
||||
http://zsnes.zophar.net/cht/
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.9 (03-11-2010) - rev. number 49d11492e2
|
||||
===============================================================================
|
||||
* Updated to new SNES9x version - now runs the following games that didn't
|
||||
work before:
|
||||
- The Mask
|
||||
* Fixed 16:9 aspect ratio issue - this seems to be a common issue with PS3s
|
||||
on modern HDTVs. There is now an 'Overscan' option inside the Settings menu
|
||||
that you can use to get the stretched screen fit just right on your TV screen.
|
||||
* Settings are saved when exiting the emulator.
|
||||
* The garbage on the right side of the screen has been fixed
|
||||
* Two sound modes are now available: Normal (same as it was before) and RSound.
|
||||
RSound is a networked audio client/server program - with this, you can route
|
||||
the music from the PS3 (SNES audio in this case) to any laptop/PC/settopbox that
|
||||
has a media player with either the RSound plugin, or a dedicated RSound server
|
||||
application (Rsd/Rsdplay). There is a documentation file and a Youtube video
|
||||
provided to help people to set it up. Latency is as low as it possibly can be -
|
||||
definitely try it out.
|
||||
* Major restructuring to the Settings screen.
|
||||
* The default ROM directory, default savestate directory can now be set inside
|
||||
the Settings screen.
|
||||
* 5-player Multitap support (was previously just 4-player)
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.8 (23-10-2010) - rev. number 768cf9df52
|
||||
===============================================================================
|
||||
* Updated to new SNES9x version - now runs the following games that didn't
|
||||
work previously (or had noise instead of sound):
|
||||
- Earthworm Jim 2
|
||||
- NBA Hangtime
|
||||
- MS Pac Man
|
||||
* PSGL driver built and in use - speed is now better at 1080p than it was
|
||||
previously at 480p. There's still a resolution switch, but there's no need
|
||||
anymore to switch to 480p - speed is the same at 1080p as it is on 480p, and
|
||||
it's damn good for the record. Enjoy.
|
||||
* All resolutions supported now
|
||||
* Added simple hardware filtering settings - Linear Interpolation and Point
|
||||
Filtering. Shaders will come later.
|
||||
* Added Aspect Ratio settings - 4:3 and 16:10 (HDTVs with 16:9 aspect ratio
|
||||
might experience that on 16:10, the screen might be slightly cut-off. We're
|
||||
working on a proper aspect ratio setting for 16:9)
|
||||
* Can now load configurable settings from snes9x.conf file stored in the
|
||||
USRDIR folder. Saving of this file will come in the next release.
|
||||
* Will now select the highest resolution your TV/monitor can support - so is
|
||||
no longer set to default at 480p.
|
||||
* No more performance difference between 1.92 pkg and 3.41 pkg.
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.7 (19-10-2010) - rev. number f2e3e0bef2
|
||||
===============================================================================
|
||||
* There's now a build for PS3s with firmwares below 3.41 (basically bigger than
|
||||
or equal to FW 1.92) and a build for PS3s with firmwares 3.41 or higher.
|
||||
* You can now switch resolutions inside the Settings screen - go from 480p to
|
||||
720p or vice versa, hence the need for two builds (480p and 720p) eliminated.
|
||||
* Zipped ROM support (ZIP/JMA)
|
||||
* Savestates are now compressed as well (NOTE: I don't know what this will
|
||||
do to your pre-existing savestates. Try to back them up first - they're
|
||||
inside the USRDIR folder of /dev_hdd0/game/SNES90000/)
|
||||
* Menu looks a whole lot better now at both 480p and 720p; crappy font has
|
||||
been put out of commission. It's now actually readable
|
||||
* Games that switch between SNES resolutions (Seiken Densetsu 3/Secret of
|
||||
Mana) are now both vertically scaled correctly - you don't even notice the
|
||||
resolution switch anymore. This is only at 480p mode - in 720p mode you will
|
||||
notice the same effect as you did previously. This will be worked on. (Halsafar)
|
||||
* A lot of settings got added to the Settings screen. For instance, it's now
|
||||
possible (on most PAL games) to run them at 60fps by setting 'Force PAL ROM
|
||||
to NTSC' to ON. This won't work for every game, however (most games after
|
||||
1993 came with region protection), and it might even result in a crash
|
||||
because you're doing something that is not deemed appropriate by either the
|
||||
SNES hardware or the emulator. A solution for PAL ROMs is worked on.
|
||||
* You can return to a previous folder inside the ROM menu by pressing the
|
||||
CIRCLE button.
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.6 (11-10-2010) - rev. number 61ecb6e1c9:
|
||||
===============================================================================
|
||||
* Savestates implemented (cmonkey69)
|
||||
* Settings screen implemented (cmonkey69)
|
||||
* Some performance improvements noticeable due to switch to more recent
|
||||
SDK - Jikkyou Oshaberi Parodius now has only a minor frame drop to 57fps on
|
||||
the character select screen but runs fine everywhere else (at 480p)
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.5 (8-10-2010):
|
||||
===============================================================================
|
||||
* Fixed the 'green ROM' loading/crashing bug - it was due to a mistake made
|
||||
when 'sorting' the file names inside a directory - the variable array that
|
||||
checked if a file was a directory was not updated. Credit goes to cmonkey69
|
||||
for fixing his own code :)
|
||||
* Moved all display code into its own file - celldisplay.cpp /
|
||||
celldisplayutil.h
|
||||
* Upgraded to latest SNES9x - git repository:
|
||||
http://board.byuu.org/viewtopic.php?f=3&t=881
|
||||
- Contains the following patches/improvements:
|
||||
- Cx4 improvement (Mega Man X2) -
|
||||
http://board.byuu.org/viewtopic.php?f=3&t=881
|
||||
- Fix Dual Orb 2 sound glitch (byuu)
|
||||
- Updated to latest WIP
|
||||
- Improvements noticed by myself (mostly APU related):
|
||||
- Jikkyou Oshaberi Parodius - far better performance - far less sound
|
||||
pops (this was one of the few games except for SuperFX ones that did
|
||||
not run perfectly)
|
||||
- Star Fox/Star Fox 2 have far less sound pops (though still there)
|
||||
- Super Mario World 2: Yoshi's Island - the spots where framerate dips
|
||||
and sound pops could usually be noticed have also been improved
|
||||
* NOTE: These games (SuperFX games - Jikkyou Oshaberi Parodius - SA-1 -
|
||||
are best played at 480p - the fps stays at 60, but the sound pops are
|
||||
very irritating at 720p with these few games)
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.4 (3-10-2010):
|
||||
===============================================================================
|
||||
* Removed the hack that caused the emulator to exit to the XMB after loading
|
||||
the fourth ROM - this was to disguise a really bad crashing bug. This hack
|
||||
no longer seems to be needed.
|
||||
* If you exit a ROM with L3+R3, you can return back to the game while inside
|
||||
the ROM Browser menu by pressing L2+R2 simultaneously.
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.3 (2-10-2010):
|
||||
===============================================================================
|
||||
* Multitap support. Start a ROM with the Triangle button inside the ROM browser
|
||||
menu.
|
||||
- This works on all controllers - PS3/USB joypads - you name it. You can
|
||||
hotswap them on the fly - you don't have to have them all inserted at the
|
||||
start of the game - you can insert them later and it will instantly recognize
|
||||
the second/third/fourth pad as that controller
|
||||
* Changed SoundInputRate from 31942 to 31960 - I heard a lot of static/
|
||||
distortion with games like Demon's Crest and Super Metroid at 31942, and
|
||||
31960 seems to be a huge improvement to that end. 31942 was a SoundInputRate
|
||||
that I had decided upon back when the emulator was still running at a 60Hz
|
||||
refresh rate instead of 59.94Hz - now that we're at 59.94Hz, we can increase
|
||||
the SoundInputRate and get better sound/video synchronization overall. Might
|
||||
increase this even more in the future - have to do some more tests.
|
||||
- In any case, as a result of changing this, most games should have improved
|
||||
sound now.
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.2 (1-10-2010):
|
||||
===============================================================================
|
||||
* Totally rewritten controller/input code (check cellpad.cpp/cellpadutil.h).
|
||||
Theoretically, input lag should be less now since the read_pad loop was
|
||||
previously hardcoded to do a pass at least two times - now it will check how
|
||||
many controllers are actually connected. So for instance, if only one
|
||||
controller is connected, it will only go through this loop where it checks
|
||||
for button input one time instead of twice - thus reducing clock cycles.
|
||||
|
||||
Also there are now function calls available such as cellPadUtilButtonPressed
|
||||
and cellPadUtilButtonReleased, which could be used in various ways.
|
||||
* The left analog stick is now mapped to the directional pad.
|
||||
* The left analog stick now works at the ROM browser menu and is a lot
|
||||
faster than the D-pad - so use this for browsing in case you have a big ROM
|
||||
list and the D-pad takes a while to browse through it.
|
||||
* Files in ROM directories are now alphabetically sorted (cmonkey69)
|
||||
* ROM browser will return to the last entered directory after quitting ROM
|
||||
* 'Quit ROM' shortcut changed to R3+L3
|
||||
* The 480p build in the last version (4.3.1) did not output at 480p but at
|
||||
576p, because the 576p mode was ticked in the PARAM.SFO. The 480p build
|
||||
will now display at 480p like it's supposed to.
|
||||
* Removed the 'Load PAL ROM' option by pressing Triangle at the ROM browser
|
||||
menu since it serves no purpose at the moment and doesn't do what it's
|
||||
supposed to.
|
||||
|
||||
===============================================================================
|
||||
Build 4.3.1 (27-9-2010):
|
||||
===============================================================================
|
||||
* There's now a 720p build and a 480p one. This is only temporary until I
|
||||
find a way to manually set resolutions without the PS3 making its own
|
||||
inferences as to what resolution I would like based on the display settings
|
||||
toggled in PARAM.SFO.
|
||||
* Got rid of a duplicate cellGcmFlush(); at the very start of the flip
|
||||
function - it should not be at the start of the function according to
|
||||
examples shown. cellGcmFlush basically forces the RSX to process all the
|
||||
GCM commands buffered in the command buffer - however, in the
|
||||
same method, this function is already called after resetting the flip
|
||||
status.
|
||||
* Made preliminary steps to sort out the PAL problems by allowing the user
|
||||
to load a ROM with the Triangle button that sets ForcePAL and the refresh
|
||||
rate to 50Hz. However, there should be a way to get at the region of the
|
||||
ROM using some sort of Snes9x function call without having to start the
|
||||
actual ROM that has been loaded. This way, I could set this automatically.
|
||||
|
||||
===============================================================================
|
||||
Build 4.3 (26-9-2010)
|
||||
===============================================================================
|
||||
* Aspect ratio set to 4:3 - doesn't yet output at 4:3 though - still big
|
||||
borders at left and right of the screen
|
||||
* Better colors
|
||||
* Runs now at native 480p resolution @ 59.94Hz refresh rate - together with
|
||||
SoundInputrate (31942), takes care of all audio/video glitches. Basically
|
||||
runs and performs like a native SNES now - or at least close.
|
||||
|
||||
===============================================================================
|
||||
Build 4.2.2
|
||||
===============================================================================
|
||||
* Exits the emulator and returns back to the XMB after having loaded the
|
||||
fourth ROM to prevent known crashing bug/black screen upon trying to load the
|
||||
fifth ROM from the ROM browser menu.
|
||||
|
||||
===============================================================================
|
||||
Build 4.2.1
|
||||
===============================================================================
|
||||
* Added a 'Quit ROM' shortcut - press R2 + L2 simultaneously in-game to go
|
||||
back to the ROM browser menu.
|
||||
|
||||
===============================================================================
|
||||
Build 4.2
|
||||
===============================================================================
|
||||
* Set SoundInputRate at 31942 (previous setting was 31968), seems to remove
|
||||
the sound pops. Sound seems to be pretty much perfect now - perhaps later
|
||||
on return to this and find the ideal value somewhere inbetween 31942 - 31950.
|
||||
|
||||
===============================================================================
|
||||
Build 4
|
||||
===============================================================================
|
||||
* Started from scratch - redownloaded 1.52, took everything from eisz to make
|
||||
it compile for PS3
|
||||
* Set SoundSync to TRUE
|
||||
* Set AutoSaveDelay to 0
|
||||
* Applied the following patches from snes9x-gtk:
|
||||
- Revision r258 - Add a fixed-point linear resampler option.
|
||||
- Revision r259 - Use the APU_DEFAULT_RESAMPLER macro.
|
||||
- Revision r260 - Optimize the linear interpolation macro.
|
||||
- Revision r272 - Merge zones' timing stuff.
|
||||
- Revision r282 - Use APU clock that yields 32040hz output instead of 32000.
|
||||
- Revision r283 - Integrate timing hack variables into the clock ratios to
|
||||
allow integers in all cases.
|
||||
- Revision r287 - Don't push samples if there aren't any.
|
||||
|
||||
* Finally, the sound scratching is gone as a result of applying all the patches
|
||||
one after another. People will still want to fiddle around with the
|
||||
SoundInputRate to get it totally perfect - the crackling is gone, that is no
|
||||
longer a problem, but if you focus really hard, you will hear a slight pop -
|
||||
SoundInputRate is now set at 31968 - try lowering it, subtract by 10.
|
||||
|
||||
In case this writeup makes it sound like the sound is bad, you will probably
|
||||
not even notice what I'm talking about here - the sound is pretty much perfect
|
||||
now.
|
||||
|
||||
===============================================================================
|
||||
Build 3
|
||||
===============================================================================
|
||||
* Patch r287 from snes9x-gtk - 'Don't push samples if there aren't any'
|
||||
* Patch r260 from snes9x-gtk - 'Optimize the linear interpolation macro'
|
||||
* Patch r272 from snes9x-gtk - 'Merge zones' timing stuff' (bSNES'
|
||||
SA-1 core integrated in SNES9x + Seiken Densetsu 2/Secret of Mana gamehack)
|
||||
* Patch r283 from snes9x-gtk - 'Integrate timing hack variables into the clock
|
||||
ratios to allow integers in all cases.'
|
||||
* Patch r282 from snes9x-gtk - 'Use APU clock that yields 32040hz output
|
||||
instead of 32000.' - Together, these two patches seem to fix the sound lag
|
||||
and pops (but crackling remains).
|
||||
* Settings.AutoSaveDelay changed from 5 to 0 - SRAM lag fix.
|
||||
* Settings.SyncSound set to TRUE.
|
||||
* SFC file support in rudimentary file browser.
|
||||
|
||||
===============================================================================
|
||||
Build 2
|
||||
===============================================================================
|
||||
* Patch r283 from snes9x-gtk - 'Integrate timing hack variables into the
|
||||
clock ratios to allow integers in all cases.'
|
||||
* Patch r282 from snes9x-gtk - 'Use APU clock that yields 32040hz output
|
||||
instead of 32000.' - Together, these two patches seem to fix the sound lag
|
||||
and pops (but crackling remains).
|
1133
PS3-SNES9x-README.txt
Normal file
10
build-all
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
echo ""
|
||||
echo "EBOOT - make $1"
|
||||
echo ""
|
||||
make -f Makefile-eboot-launcher $1
|
||||
echo ""
|
||||
echo "SNES9x - make $1"
|
||||
echo ""
|
||||
make -f Makefile $1
|
||||
|
2
buildtools/PS3Py/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
*.pyc
|
BIN
buildtools/PS3Py/ICON0.PNG
Normal file
After Width: | Height: | Size: 14 KiB |
9
buildtools/PS3Py/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
all: pkgcrypt.so
|
||||
|
||||
pkgcrypt.so: crypt.c setup.py
|
||||
@python setup.py build --compiler=mingw32
|
||||
@cp build/lib.*/pkgcrypt.so .
|
||||
|
||||
clean:
|
||||
rm -rf build pkgcrypt.so
|
282
buildtools/PS3Py/Struct.py
Normal file
@ -0,0 +1,282 @@
|
||||
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 StructException(Exception):
|
||||
pass
|
||||
|
||||
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
|
BIN
buildtools/PS3Py/build/lib.linux-x86_64-2.7/pkgcrypt.so
Executable file
BIN
buildtools/PS3Py/build/lib.win32-2.7/pkgcrypt.pyd
Normal file
BIN
buildtools/PS3Py/build/temp.linux-x86_64-2.7/crypt.o
Normal file
BIN
buildtools/PS3Py/build/temp.win32-2.7/Release/crypt.o
Normal file
@ -0,0 +1,3 @@
|
||||
LIBRARY pkgcrypt.pyd
|
||||
EXPORTS
|
||||
initpkgcrypt
|
97
buildtools/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);
|
||||
}
|
||||
|
||||
|
275
buildtools/PS3Py/fself.py
Normal file
@ -0,0 +1,275 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import with_statement
|
||||
from Struct import Struct
|
||||
import struct
|
||||
import getopt
|
||||
import sys
|
||||
|
||||
"""
|
||||
This is a quick and dirty implementation of make_fself based on the
|
||||
documentation collected here:
|
||||
http://ps3wiki.lan.st/index.php/Self_file_format
|
||||
It's not ment to look pretty, or be well documented but just provide
|
||||
an alternative to using the illegal Sony SDK until a better solution
|
||||
is released. (Such as a propper ELF loader built into lv2)
|
||||
-- phiren
|
||||
"""
|
||||
|
||||
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
|
||||
|
||||
class phdrOffset(Struct):
|
||||
__endian__ = Struct.BE
|
||||
def __format__(self):
|
||||
self.offset = Struct.uint64
|
||||
self.size = Struct.uint64
|
||||
self.unk1 = Struct.uint32
|
||||
self.unk2 = Struct.uint32
|
||||
self.unk3 = Struct.uint32
|
||||
self.unk4 = Struct.uint32
|
||||
|
||||
class DigestSubHeader(Struct):
|
||||
__endian__ = Struct.BE
|
||||
def __format__(self):
|
||||
self.type = Struct.uint32
|
||||
self.size = Struct.uint32
|
||||
self.cont = Struct.uint64
|
||||
|
||||
class DigestType2(Struct):
|
||||
__endian__ = Struct.BE
|
||||
def __format__(self):
|
||||
self.magicBits = Struct.uint8[0x14]
|
||||
self.digest = Struct.uint8[0x14]
|
||||
self.padding = Struct.uint8[0x08]
|
||||
|
||||
class DigestTypeNPDRM(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]
|
||||
|
||||
class Elf64_ehdr(Struct):
|
||||
__endian__ = Struct.BE
|
||||
def __format__(self):
|
||||
self.ident = Struct.uint8[16]
|
||||
self.type = Struct.uint16
|
||||
self.machine = Struct.uint16
|
||||
self.version = Struct.uint32
|
||||
self.entry = Struct.uint64
|
||||
self.phoff = Struct.uint64
|
||||
self.shoff = Struct.uint64
|
||||
self.flags = Struct.uint32
|
||||
self.ehsize = Struct.uint16
|
||||
self.phentsize = Struct.uint16
|
||||
self.phnum = Struct.uint16
|
||||
self.shentsize = Struct.uint16
|
||||
self.shnum = Struct.uint16
|
||||
self.shstrndx = Struct.uint16
|
||||
|
||||
class Elf64_phdr(Struct):
|
||||
__endian__ = Struct.BE
|
||||
def __format__(self):
|
||||
self.type = Struct.uint32
|
||||
self.flags = Struct.uint32
|
||||
self.offset = Struct.uint64
|
||||
self.vaddr = Struct.uint64
|
||||
self.paddr = Struct.uint64
|
||||
self.filesz = Struct.uint64
|
||||
self.memsz = Struct.uint64
|
||||
self.align = Struct.uint64
|
||||
|
||||
def align(address, alignment):
|
||||
padding = alignment - (address % alignment)
|
||||
return address + padding
|
||||
|
||||
def padding(address, alignment):
|
||||
padding = alignment - (address % alignment)
|
||||
return "\0" * padding
|
||||
|
||||
def readElf(infile):
|
||||
with open(infile, 'rb') as fp:
|
||||
data = fp.read()
|
||||
ehdr = Elf64_ehdr()
|
||||
ehdr.unpack(data[0:len(ehdr)])
|
||||
phdrs = []
|
||||
offset = ehdr.phoff
|
||||
for i in range(ehdr.phnum):
|
||||
phdr = Elf64_phdr()
|
||||
phdr.unpack(data[offset:offset+len(phdr)])
|
||||
offset += len(phdr)
|
||||
phdrs.append(phdr)
|
||||
|
||||
return data, ehdr, phdrs
|
||||
|
||||
def genDigest(out, npdrm):
|
||||
digestSubHeader = DigestSubHeader()
|
||||
digestType2 = DigestType2()
|
||||
digestTypeNPDRM = DigestTypeNPDRM()
|
||||
|
||||
digestSubHeader.type = 2
|
||||
digestSubHeader.size = 0x40
|
||||
if npdrm:
|
||||
digestSubHeader.cont = 1
|
||||
out.write(digestSubHeader.pack())
|
||||
|
||||
digestType2.magicBits = (0x62, 0x7c, 0xb1, 0x80, 0x8a, 0xb9, 0x38, 0xe3, 0x2c, 0x8c, 0x09, 0x17, 0x08, 0x72, 0x6a, 0x57, 0x9e, 0x25, 0x86, 0xe4)
|
||||
out.write(digestType2.pack())
|
||||
|
||||
if not npdrm:
|
||||
return
|
||||
|
||||
digestSubHeader.type = 3
|
||||
digestSubHeader.size = 0x90
|
||||
digestSubHeader.cont = 0
|
||||
out.write(digestSubHeader.pack())
|
||||
|
||||
digestTypeNPDRM.magic = 0x4e504400
|
||||
digestTypeNPDRM.unk1 = 1
|
||||
digestTypeNPDRM.drmType = 2
|
||||
digestTypeNPDRM.unk2 = 1
|
||||
digestTypeNPDRM.contentID = [0x30] * 0x2f + [0]
|
||||
digestTypeNPDRM.fileSHA1 = (0x42, 0x69, 0x74, 0x65, 0x20, 0x4d, 0x65, 0x2c, 0x20, 0x53, 0x6f, 0x6e, 0x79, 0x00, 0xde, 0x07)
|
||||
digestTypeNPDRM.notSHA1 = [0xab] * 0x10
|
||||
digestTypeNPDRM.notXORKLSHA1 = [0x01] * 0x0f + [0x02]
|
||||
out.write(digestTypeNPDRM.pack())
|
||||
|
||||
|
||||
def createFself(npdrm, infile, outfile="EBOOT.BIN"):
|
||||
elf, ehdr, phdrs = readElf(infile)
|
||||
|
||||
header = SelfHeader()
|
||||
appinfo = AppInfo()
|
||||
digestSubHeader = DigestSubHeader()
|
||||
digestType2 = DigestType2()
|
||||
digestTypeNPDRM = DigestTypeNPDRM()
|
||||
phdr = Elf64_phdr()
|
||||
phdrOffsets = phdrOffset()
|
||||
|
||||
header.magic = 0x53434500
|
||||
header.headerVer = 2
|
||||
header.flags = 0x8000
|
||||
header.type = 1
|
||||
header.encryptedSize = len(elf)
|
||||
header.unknown = 3
|
||||
header.AppInfo = align(len(header), 0x10)
|
||||
header.elf = align(header.AppInfo + len(appinfo), 0x10)
|
||||
header.phdr = header.elf + len(ehdr)
|
||||
phdrOffsetsOffset = header.phdr + len(phdr) * len(phdrs)
|
||||
header.phdrOffsets = align(phdrOffsetsOffset, 0x10);
|
||||
|
||||
header.sceVersion = 0
|
||||
|
||||
digestOffset = header.phdrOffsets + len(phdrs) * len(phdrOffsets)
|
||||
header.digest = align(digestOffset, 0x10)
|
||||
header.digestSize = len(digestSubHeader) + len(digestType2
|
||||
)
|
||||
if npdrm:
|
||||
header.digestSize += len(digestSubHeader) + len(digestTypeNPDRM)
|
||||
|
||||
endofHeader = header.digest + header.digestSize
|
||||
elfOffset = align(endofHeader, 0x80)
|
||||
|
||||
header.shdr = elfOffset + ehdr.shoff
|
||||
header.headerSize = elfOffset
|
||||
header.meta = endofHeader - 0x10
|
||||
|
||||
appinfo.authid = 0x1010000001000003
|
||||
appinfo.unknown = 0x1000002
|
||||
if npdrm:
|
||||
appinfo.appType = 0x8
|
||||
else:
|
||||
appinfo.appType = 0x4
|
||||
appinfo.appVersion = 0x0001000000000000
|
||||
|
||||
offsets = []
|
||||
for phdr in phdrs:
|
||||
offset = phdrOffset()
|
||||
offset.offset = phdr.offset + elfOffset
|
||||
offset.size = phdr.filesz
|
||||
offset.unk1 = 1
|
||||
offset.unk2 = 0
|
||||
offset.unk3 = 0
|
||||
if phdr.type == 1:
|
||||
offset.unk4 = 2
|
||||
else:
|
||||
offset.unk4 = 0
|
||||
offsets.append(offset)
|
||||
out = open(outfile, 'wb')
|
||||
out.write(header.pack())
|
||||
out.write(padding(len(header), 0x10))
|
||||
out.write(appinfo.pack())
|
||||
out.write(padding(header.AppInfo + len(appinfo), 0x10))
|
||||
out.write(ehdr.pack())
|
||||
for phdr in phdrs:
|
||||
out.write(phdr.pack())
|
||||
out.write(padding(phdrOffsetsOffset, 0x10))
|
||||
for offset in offsets:
|
||||
out.write(offset.pack())
|
||||
out.write(padding(digestOffset, 0x10))
|
||||
genDigest(out, npdrm)
|
||||
out.write(padding(endofHeader, 0x80))
|
||||
out.write(elf)
|
||||
|
||||
|
||||
def usage():
|
||||
print """fself.py usage:
|
||||
fself.py [options] input.elf output.self
|
||||
If output file is not specified, fself.py will default to EBOOT.BIN
|
||||
Options:
|
||||
--npdrm: will output a file for use with pkg.py."""
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hn", ["help", "npdrm"])
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
npdrm = False
|
||||
for opt, arg in opts:
|
||||
if opt in ("-h", "--help"):
|
||||
usage()
|
||||
sys.exit(2)
|
||||
elif opt in ("-n", "--npdrm"):
|
||||
npdrm = True
|
||||
else:
|
||||
usage()
|
||||
|
||||
if len(args) == 1:
|
||||
createFself(npdrm, args[0])
|
||||
elif len(args) == 2:
|
||||
createFself(npdrm, args[0], args[1])
|
||||
else:
|
||||
usage()
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
2
buildtools/PS3Py/make.bat
Normal file
@ -0,0 +1,2 @@
|
||||
make.exe
|
||||
pause
|
601
buildtools/PS3Py/pkg.py
Normal file
@ -0,0 +1,601 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import with_statement
|
||||
from Struct import Struct
|
||||
from fself import SelfHeader, AppInfo
|
||||
|
||||
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
|
||||
|
||||
debug = False
|
||||
|
||||
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 = ""
|
||||
def doWork(self, decrypteddata, context = None):
|
||||
if context == None:
|
||||
self.fileName = nullterm(decrypteddata[self.fileNameOff:self.fileNameOff+self.fileNameLength])
|
||||
else:
|
||||
self.fileName = nullterm(crypt(context, decrypteddata[self.fileNameOff:self.fileNameOff+self.fileNameLength], self.fileNameLength))
|
||||
def dump(self, directory, data, header):
|
||||
if self.flags & 0xFF == 0x4:
|
||||
try:
|
||||
os.makedirs(directory + "/" + self.fileName)
|
||||
except Exception, e:
|
||||
print
|
||||
|
||||
else:
|
||||
tFile = open(directory + "/" + self.fileName, "wb")
|
||||
tFile.write(data[self.fileOff:self.fileOff+self.fileSize])
|
||||
|
||||
|
||||
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])
|
||||
|
||||
import pkgcrypt
|
||||
|
||||
def crypt(key, inbuf, length):
|
||||
if not isinstance(key, list):
|
||||
return ""
|
||||
# Call our ultra fast c implemetation
|
||||
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 listPkg(filename):
|
||||
with open(filename, 'rb') as fp:
|
||||
data = fp.read()
|
||||
offset = 0
|
||||
header = Header()
|
||||
header.unpack(data[offset:offset+len(header)])
|
||||
print header
|
||||
print
|
||||
|
||||
assert header.type == 0x00000001, 'Unsupported Type'
|
||||
if header.itemCount > 0:
|
||||
print 'Listing: "' + filename + '"'
|
||||
print "+) overwrite, -) no overwrite"
|
||||
print
|
||||
dataEnc = data[header.dataOff:header.dataOff+header.dataSize]
|
||||
context = keyToContext(header.QADigest)
|
||||
|
||||
decData = crypt(context, dataEnc, len(FileHeader())*header.itemCount)
|
||||
|
||||
fileDescs = []
|
||||
for i in range(0, header.itemCount):
|
||||
fileD = FileHeader()
|
||||
fileD.unpack(decData[0x20 * i:0x20 * i + 0x20])
|
||||
fileDescs.append(fileD)
|
||||
for fileD in fileDescs:
|
||||
fileD.doWork(dataEnc, context)
|
||||
out = ""
|
||||
if fileD.flags & 0xFF == TYPE_NPDRMSELF:
|
||||
out += " NPDRM SELF:"
|
||||
elif fileD.flags & 0xFF == TYPE_DIRECTORY:
|
||||
out += " directory:"
|
||||
elif fileD.flags & 0xFF == TYPE_RAW:
|
||||
out += " raw data:"
|
||||
else:
|
||||
out += " unknown:"
|
||||
if (fileD.flags & TYPE_OVERWRITE_ALLOWED ) != 0:
|
||||
out += "+"
|
||||
else:
|
||||
out += "-"
|
||||
out += "%11d: " % fileD.fileSize
|
||||
out += fileD.fileName
|
||||
print out,
|
||||
print
|
||||
#print fileD
|
||||
def unpack(filename):
|
||||
with open(filename, 'rb') as fp:
|
||||
data = fp.read()
|
||||
offset = 0
|
||||
header = Header()
|
||||
header.unpack(data[offset:offset+len(header)])
|
||||
if debug:
|
||||
print header
|
||||
print
|
||||
|
||||
assert header.type == 0x00000001, 'Unsupported Type'
|
||||
if header.itemCount > 0:
|
||||
dataEnc = data[header.dataOff:header.dataOff+header.dataSize]
|
||||
context = keyToContext(header.QADigest)
|
||||
|
||||
decData = crypt(context, dataEnc, header.dataSize)
|
||||
directory = nullterm(header.contentID)
|
||||
try:
|
||||
os.makedirs(directory)
|
||||
except Exception, e:
|
||||
pass
|
||||
fileDescs = []
|
||||
for i in range(0, header.itemCount):
|
||||
fileD = FileHeader()
|
||||
fileD.unpack(decData[0x20 * i:0x20 * i + 0x20])
|
||||
fileD.doWork(decData)
|
||||
fileDescs.append(fileD)
|
||||
if debug:
|
||||
print fileD
|
||||
fileD.dump(directory, decData, header)
|
||||
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 """pky.py 0.5"""
|
||||
|
||||
def main():
|
||||
global debug
|
||||
extract = False
|
||||
list = False
|
||||
contentid = None
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hx:dvl:c:", ["help", "extract=", "debug","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 ("-d", "--debug"):
|
||||
debug = True
|
||||
elif opt in ("-c", "--contentid"):
|
||||
contentid = arg
|
||||
else:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
if extract:
|
||||
unpack(fileToExtract)
|
||||
elif list:
|
||||
listPkg(fileToList)
|
||||
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()
|
BIN
buildtools/PS3Py/pkgcrypt.pyd
Normal file
8
buildtools/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])
|
307
buildtools/PS3Py/sfo.py
Normal file
@ -0,0 +1,307 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import with_statement
|
||||
from xml.dom.minidom import Document, parse, parseString
|
||||
from Struct import Struct
|
||||
import struct
|
||||
import sys
|
||||
import getopt
|
||||
debug = None
|
||||
pretty = None
|
||||
|
||||
SFO_MAGIC = 0x46535000
|
||||
SFO_STRING = 2
|
||||
SFO_INT = 4
|
||||
def nullterm(str_plus):
|
||||
z = str_plus.find('\0')
|
||||
if z != -1:
|
||||
return str_plus[:z]
|
||||
else:
|
||||
return str_plus
|
||||
|
||||
class Header(Struct):
|
||||
__endian__ = Struct.LE
|
||||
def __format__(self):
|
||||
self.magic = Struct.uint32
|
||||
self.unk1 = Struct.uint32
|
||||
self.KeyOffset = Struct.uint32
|
||||
self.ValueOffset = Struct.uint32
|
||||
self.PairCount = Struct.uint32
|
||||
def __str__(self):
|
||||
out = ""
|
||||
out += "[X] Magic: %08x\n" % self.magic
|
||||
out += "[ ] Unk1: %08x\n" % self.unk1
|
||||
out += "[X] Key Offset: %08x\n" % self.KeyOffset
|
||||
out += "[X] Value Offset: %08x\n" % self.ValueOffset
|
||||
out += "[X] Pair Count: %08x" % self.PairCount
|
||||
return out
|
||||
|
||||
class Entry(Struct):
|
||||
__endian__ = Struct.LE
|
||||
def __format__(self):
|
||||
self.key_off = Struct.uint16
|
||||
self.unk1 = Struct.uint8
|
||||
self.value_type = Struct.uint8
|
||||
self.value_len = Struct.uint32
|
||||
self.padded_len = Struct.uint32
|
||||
self.value_off = Struct.uint32
|
||||
def __str__(self):
|
||||
out = ""
|
||||
out += "[X] Key Offset: %04x\n" % self.key_off
|
||||
out += "[ ] Unk1: %02x\n" % self.unk1
|
||||
out += "[/] Value Type: %02x\n" % self.value_type
|
||||
out += "[X] Value Length: %08x\n" % self.value_len
|
||||
out += "[X] Padded Length: %08x\n" % self.padded_len
|
||||
out += "[X] Value Offset: %08x" % self.value_off
|
||||
return out
|
||||
def PrettyPrint(self, data, key_off, value_off):
|
||||
out = ""
|
||||
out += "[X] Key: '%s'[%04x]\n" % (nullterm(data[self.key_off + key_off:]), self.key_off)
|
||||
out += "[/] Unk: %02x\n" % (self.unk1)
|
||||
out += "[/] Value Type: %02x\n" % self.value_type
|
||||
out += "[X] Value Length: %08x\n" % self.value_len
|
||||
out += "[X] Padded Length: %08x\n" % self.padded_len
|
||||
out += "[X] Value Offset: %08x" % self.value_off
|
||||
if self.value_type == SFO_STRING:
|
||||
out += "[X] Value: '%s'[%08x]" % (nullterm(data[self.value_off + value_off:]), self.value_off+value_off)
|
||||
elif self.value_type == SFO_INT:
|
||||
out += "[X] Value: %d[%08x]" % (struct.unpack('<I', data[self.value_off + value_off:self.value_off + value_off + 4])[0], self.value_off+value_off)
|
||||
else:
|
||||
out += "[X] Value Type Unknown"
|
||||
return out
|
||||
|
||||
def usage():
|
||||
print """usage:
|
||||
python sfo.py"""
|
||||
|
||||
def version():
|
||||
print """sfo.py 0.2"""
|
||||
|
||||
def listSFO(file):
|
||||
global debug
|
||||
global pretty
|
||||
with open(file, 'rb') as fp:
|
||||
stuff = {}
|
||||
data = fp.read()
|
||||
offset = 0
|
||||
header = Header()
|
||||
header.unpack(data[offset:offset+len(header)])
|
||||
if debug:
|
||||
print header
|
||||
print
|
||||
assert header.magic == SFO_MAGIC
|
||||
assert header.unk1 == 0x00000101
|
||||
offset += len(header)
|
||||
off1 = header.KeyOffset
|
||||
off2 = header.ValueOffset
|
||||
for x in xrange(header.PairCount):
|
||||
entry = Entry()
|
||||
entry.unpack(data[offset:offset+len(entry)])
|
||||
if debug and not pretty:
|
||||
print entry
|
||||
print
|
||||
if debug and pretty:
|
||||
print entry.PrettyPrint(data, off1, off2)
|
||||
print
|
||||
key = nullterm(data[off1+entry.key_off:])
|
||||
if entry.value_type == SFO_STRING:
|
||||
value = nullterm(data[off2+entry.value_off:])
|
||||
else:
|
||||
value = struct.unpack('<I', data[entry.value_off + off2:entry.value_off + off2 + 4])[0]
|
||||
stuff[key] = value
|
||||
offset += len(entry)
|
||||
if not debug:
|
||||
print stuff
|
||||
def convertToXml(sfofile, xml):
|
||||
doc = Document()
|
||||
sfo = doc.createElement("sfo")
|
||||
|
||||
|
||||
with open(sfofile, 'rb') as fp:
|
||||
stuff = {}
|
||||
data = fp.read()
|
||||
offset = 0
|
||||
header = Header()
|
||||
header.unpack(data[offset:offset+len(header)])
|
||||
if debug:
|
||||
print header
|
||||
print
|
||||
assert header.magic == SFO_MAGIC
|
||||
assert header.unk1 == 0x00000101
|
||||
offset += len(header)
|
||||
off1 = header.KeyOffset
|
||||
off2 = header.ValueOffset
|
||||
for x in xrange(header.PairCount):
|
||||
entry = Entry()
|
||||
entry.unpack(data[offset:offset+len(entry)])
|
||||
if debug and not pretty:
|
||||
print entry
|
||||
print
|
||||
if debug and pretty:
|
||||
print entry.PrettyPrint(data, off1, off2)
|
||||
print
|
||||
key = nullterm(data[off1+entry.key_off:])
|
||||
valuenode = doc.createElement("value")
|
||||
valuenode.setAttribute("name", key)
|
||||
if entry.value_type == SFO_STRING:
|
||||
value = nullterm(data[off2+entry.value_off:])
|
||||
valuenode.setAttribute("type", "string")
|
||||
valuenode.appendChild(doc.createTextNode(value))
|
||||
else:
|
||||
value = struct.unpack('<I', data[entry.value_off + off2:entry.value_off + off2 + 4])[0]
|
||||
valuenode.setAttribute("type", "integer")
|
||||
valuenode.appendChild(doc.createTextNode("%d" % value))
|
||||
sfo.appendChild(valuenode)
|
||||
stuff[key] = value
|
||||
offset += len(entry)
|
||||
if not debug:
|
||||
print stuff
|
||||
|
||||
doc.appendChild(sfo)
|
||||
file = open(xml, "wb" )
|
||||
doc.writexml(file, '', '\t', '\n' )
|
||||
file.close()
|
||||
|
||||
def getText(nodelist):
|
||||
rc = []
|
||||
for node in nodelist:
|
||||
if node.nodeType == node.TEXT_NODE:
|
||||
rc.append(node.data)
|
||||
return (''.join(rc)).strip()
|
||||
def align(num, alignment):
|
||||
return (num + alignment - 1) & ~(alignment-1)
|
||||
def convertToSFO(xml, sfofile, forcetitle, forceappid):
|
||||
dom = parse(xml)
|
||||
nodes = dom.getElementsByTagName("value")
|
||||
kvs = []
|
||||
for node in nodes:
|
||||
if node.hasAttributes():
|
||||
type = None
|
||||
name = None
|
||||
for i in range(node.attributes.length):
|
||||
if(node.attributes.item(i).name == "type"):
|
||||
type = node.attributes.item(i).value
|
||||
if(node.attributes.item(i).name == "name"):
|
||||
name = node.attributes.item(i).value
|
||||
if name != None and type != None:
|
||||
if name == "TITLE" and forcetitle != None:
|
||||
kvs.append((name, forcetitle))
|
||||
elif name == "TITLE_ID" and forceappid != None:
|
||||
kvs.append((name, forceappid))
|
||||
elif type == "string":
|
||||
kvs.append((name, getText(node.childNodes)))
|
||||
elif type == "integer":
|
||||
kvs.append((name, int(getText(node.childNodes))))
|
||||
header = Header()
|
||||
header.magic = SFO_MAGIC
|
||||
header.unk1 = 0x00000101
|
||||
header.PairCount = len(kvs)
|
||||
entries = []
|
||||
keyoff = 0
|
||||
valueoff = 0
|
||||
for (k,v) in kvs:
|
||||
entry = Entry()
|
||||
entry.key_off = keyoff
|
||||
entry.unk1 = 4
|
||||
if isinstance(v, int):
|
||||
entry.value_type = SFO_INT
|
||||
entry.value_len = 4
|
||||
entry.padded_len = 4
|
||||
else:
|
||||
entry.value_type = SFO_STRING
|
||||
entry.value_len = len(v) + 1
|
||||
alignment = 4
|
||||
if k == "TITLE":
|
||||
alignment = 0x80
|
||||
elif k == "LICENSE":
|
||||
alignment = 0x200
|
||||
elif k == "TITLE_ID":
|
||||
alignment = 0x10
|
||||
|
||||
entry.padded_len = align(entry.value_len, alignment)
|
||||
entry.value_off = valueoff
|
||||
keyoff += len(k)+1
|
||||
valueoff += entry.padded_len
|
||||
entries.append(entry)
|
||||
header.KeyOffset = len(Header()) + 0x10 * header.PairCount
|
||||
header.ValueOffset = align(header.KeyOffset + keyoff, 4)
|
||||
keypad = header.ValueOffset - (header.KeyOffset + keyoff)
|
||||
valuepad = header.ValueOffset - (header.KeyOffset + keyoff)
|
||||
file = open(sfofile, "wb")
|
||||
file.write(header.pack())
|
||||
for entry in entries:
|
||||
file.write(entry.pack())
|
||||
for k,v in kvs:
|
||||
file.write(k + '\0')
|
||||
file.write('\0' * keypad)
|
||||
for k,v in kvs:
|
||||
if isinstance(v, int):
|
||||
file.write(struct.pack('<I', v))
|
||||
else:
|
||||
alignment = 4
|
||||
if k == "TITLE":
|
||||
alignment = 0x80
|
||||
elif k == "LICENSE":
|
||||
alignment = 0x200
|
||||
elif k == "TITLE_ID":
|
||||
alignment = 0x10
|
||||
file.write(v + '\0')
|
||||
file.write('\0' * (align(len(v) + 1, alignment) - (len(v) +1)))
|
||||
file.close()
|
||||
def main():
|
||||
global debug
|
||||
global pretty
|
||||
debug = False
|
||||
pretty = False
|
||||
list = False
|
||||
fileToList = None
|
||||
toxml = False
|
||||
fromxml = False
|
||||
forcetitle = None
|
||||
forceappid = None
|
||||
if len(sys.argv) < 1:
|
||||
return
|
||||
if "python" in sys.argv[0]:
|
||||
sys.argv = sys.argv[1:]
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hdvpl:tf", ["help", "debug","version", "pretty", "list=", "toxml", "fromxml", "title=", "appid="])
|
||||
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 ("-l", "--list"):
|
||||
fileToList = arg
|
||||
list = True
|
||||
elif opt in ("-d", "--debug"):
|
||||
debug = True
|
||||
elif opt in ("-p", "--pretty"):
|
||||
pretty = True
|
||||
elif opt in ("-t", "--toxml"):
|
||||
toxml = True
|
||||
elif opt in ("-f", "--fromxml"):
|
||||
fromxml = True
|
||||
elif opt in ("--title"):
|
||||
forcetitle = arg
|
||||
elif opt in ("--appid"):
|
||||
forceappid = arg
|
||||
else:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
if list:
|
||||
listSFO(fileToList)
|
||||
elif toxml and not fromxml and len(args) == 2:
|
||||
convertToXml(args[0], args[1])
|
||||
elif fromxml and not toxml and len(args) == 2:
|
||||
convertToSFO(args[0], args[1], forcetitle, forceappid)
|
||||
else:
|
||||
usage()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
39
buildtools/PS3Py/sfo.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" ?>
|
||||
<sfo>
|
||||
<value name="APP_VER" type="string">
|
||||
01.00
|
||||
</value>
|
||||
<value name="ATTRIBUTE" type="integer">
|
||||
0
|
||||
</value>
|
||||
<value name="BOOTABLE" type="integer">
|
||||
1
|
||||
</value>
|
||||
<value name="CATEGORY" type="string">
|
||||
HG
|
||||
</value>
|
||||
<value name="LICENSE" type="string">
|
||||
This application was created with the official non-official SDK called PSL1GHT, for more information visit http://www.psl1ght.com/ . This is in no way associated with Sony Computer Entertainment Inc., please do not contact them for help, they will not be able to provide it.
|
||||
</value>
|
||||
<value name="PARENTAL_LEVEL" type="integer">
|
||||
0
|
||||
</value>
|
||||
<value name="PS3_SYSTEM_VER" type="string">
|
||||
01.8000
|
||||
</value>
|
||||
<value name="RESOLUTION" type="integer">
|
||||
63
|
||||
</value>
|
||||
<value name="SOUND_FORMAT" type="integer">
|
||||
279
|
||||
</value>
|
||||
<value name="TITLE" type="string">
|
||||
Test - PSL1GHT
|
||||
</value>
|
||||
<value name="TITLE_ID" type="string">
|
||||
TEST00000
|
||||
</value>
|
||||
<value name="VERSION" type="string">
|
||||
01.00
|
||||
</value>
|
||||
</sfo>
|
2387
docs/changes.txt
Normal file
68
docs/control-inputs.txt
Normal file
@ -0,0 +1,68 @@
|
||||
Control input names are completely defined by the individual ports. This
|
||||
document is intended to collect the rules for all ports.
|
||||
|
||||
The various meta-characters in the rules are:
|
||||
# - A number. The range is detemined by the context
|
||||
## - A two-digit number (i.e. with leading zeros)
|
||||
[...] - Something optional
|
||||
(...) - For grouping with |
|
||||
| - "or", choose one of the options.
|
||||
<...> - A named field
|
||||
{...} - A list of possible values. Multiple values may be used, but they
|
||||
must be in the order listed and joined with +-signs.
|
||||
"" - 'ditto', used to indicate the same list as the above line.
|
||||
|
||||
================================================================================
|
||||
Unix
|
||||
================================================================================
|
||||
|
||||
Input names:
|
||||
Jxx:Axis# Axis # on joystick xx. Axis0 may be
|
||||
Up/Down, and Axis1 Left/Right.
|
||||
Jxx:B# Button # on joystick xx.
|
||||
|
||||
Jxx:{M1,M2,M3,M4,M5,M6,M7,M8}+B# Used with the 'JSx Meta#' port
|
||||
Jxx:{M1,M2,M3,M4,M5,M6,M7,M8}+Axis# command.
|
||||
|
||||
Jxx:X+B# Used to 'define' this key for all
|
||||
Jxx:X+Axis# combinations of JS Meta.
|
||||
|
||||
Port-specific Commands:
|
||||
JSx Meta# Used to specify modifier keys (i.e. Shift, Control) to
|
||||
affect the specified joystick. For example, you could
|
||||
map J00:B20 to "JS0 Meta1", then map J00:B0 to "Joypad1
|
||||
A" and J00:M1+B0 to "Joypad1 Turbo A". '#' may range
|
||||
from 1-8.
|
||||
|
||||
Jsx ToggleMeta# Like the above, but toggles the meta-state each time
|
||||
the button is pressed.
|
||||
|
||||
================================================================================
|
||||
Unix/X11
|
||||
================================================================================
|
||||
|
||||
Keyboard Input:
|
||||
|
||||
Note that only one keyboard (K00) is currently supported. If you know how
|
||||
to support multiple keyboards (and can test it!), feel free to fix x11.cpp
|
||||
and delete this note.
|
||||
|
||||
Keyboard modifiers are S=Shift, C=Control, A=Alt, M=Meta. Combine them in
|
||||
order, i.e. all 4 would be "SCAM".
|
||||
|
||||
Kxx:<keyname> Key names are as recognized by XStringToKeysym.
|
||||
Kxx:<mods>+<keyname> Note however that keys are mapped by keycode,
|
||||
so for example on a standard qwerty keyboard
|
||||
"K00:colon" and "K00:semicolon" are identical.
|
||||
|
||||
Pointer Input:
|
||||
|
||||
Note that only one mouse (M00) is currently supported. If you know how to
|
||||
support multiple pointing devices (and can test it!), feel free to fix
|
||||
x11.cpp and delete this note.
|
||||
|
||||
Mxx:Pointer Map the mouse pointer. If someone has a mouse
|
||||
Mxx:Pointer# device with multiple pointers, fix x11.cpp to
|
||||
report that and you can use the second syntax.
|
||||
|
||||
Mxx:B# Mouse buttons.
|
97
docs/controls.txt
Normal file
@ -0,0 +1,97 @@
|
||||
This lists the available commands, excluding the ones you get back from
|
||||
S9xGetAllSnes9xCommands(). The various meta-characters are:
|
||||
# - A number. The range is detemined by the context
|
||||
## - A two-digit number (i.e. with leading zeros)
|
||||
[...] - Something optional
|
||||
(...) - For grouping with |
|
||||
| - "or", choose one of the options.
|
||||
<...> - A named field
|
||||
{...} - A list of possible values. Multiple values may be used, but they
|
||||
must be in the order listed and joined with +-signs.
|
||||
"" - 'ditto', used to indicate the same list as the above line.
|
||||
|
||||
Speeds are: Var, Slow, Med, and Fast. 'Var' starts slow and speeds up as the
|
||||
button is held.
|
||||
|
||||
Axes are: Left/Right, Right/Left, Up/Down, Down/Up, Y/A, A/Y, X/B, B/X, L/R,
|
||||
and R/L. Negative is listed first (i.e. "Y/A" means negative deflection is
|
||||
towards Y, while "A/Y" means negative deflection is towards A).
|
||||
|
||||
AxisToPointer, ButtonToPointer, and AxisToButtons allow for translating
|
||||
between different input types. There are 8 'pointers' with IDs
|
||||
PseudoPointerBase+0 to PseudoPointerBase+7, and 256 'buttons' with IDs
|
||||
PseudoButtonBase+0 to PseudoButtonBase+255. So for example,
|
||||
"AxisToButtons 0/255 T=50%" would take the axis data, and do
|
||||
S9xReportButton(PseudoButtonBase+0,1) when said axis goes past 50% in the
|
||||
negative direction and S9xReportButton(PseudoButtonBase+255,1) when it goes
|
||||
over 50% deflection in the positive direction. Similarly, it will do
|
||||
S9xReportButton(...,0) when the deflection drops under 50% in either
|
||||
direction. "ButtonToPointer 1u Slow" would move the pointer with ID
|
||||
PseudoPointerBase+0 up one pixel per frame as long as the button is pressed
|
||||
(reporting this change at the end of each frame).
|
||||
|
||||
---------------
|
||||
Button Commands
|
||||
---------------
|
||||
|
||||
Joypad# {Up, Down, Left, Right, A, B, X, Y, L, R, Start, Select}
|
||||
Joypad# Turbo ""
|
||||
Joypad# Sticky ""
|
||||
Joypad# StickyTurbo ""
|
||||
Joypad# ToggleTurbo ""
|
||||
Joypad# ToggleSticky ""
|
||||
Joypad# ToggleStickyTurbo ""
|
||||
|
||||
Mouse# (L|R|LR)
|
||||
|
||||
Superscope AimOffscreen
|
||||
Superscope {Fire, Cursor, ToggleTurbo, Pause}
|
||||
Superscope AimOffscreen ""
|
||||
|
||||
Justifier# AimOffscreen
|
||||
Justifier# {Trigger, Start}
|
||||
Justifier# AimOffscreen ""
|
||||
|
||||
ButtonToPointer #[u|d][l|r] <speed> ; NOTE: "# <speed>" is invalid
|
||||
|
||||
-------------
|
||||
Axis Commands
|
||||
-------------
|
||||
|
||||
Joypad# Axis <axis> T=#% ; T = 0.1 to 100 by tenths
|
||||
AxisToButtons #/# T=#% ; neg then pos, range 0-255, T as above
|
||||
AxisToPointer #(h|v) [-]<speed> ; NOTE: '-' inverts the axis
|
||||
|
||||
----------------
|
||||
Pointer Commands
|
||||
----------------
|
||||
|
||||
Pointer {Mouse1, Mouse2, Superscope, Justifier1, Justifier2}
|
||||
|
||||
------
|
||||
Multis
|
||||
------
|
||||
|
||||
Multis are a type of button command. The basic format of a multi is "{...}",
|
||||
where the '...' consists of 1 or more valid non-multi button command
|
||||
strings. The braces are literal, not metacharacters. Subcommands separated
|
||||
by commas are executed one after the next. Semicolons skip one frame before
|
||||
continuing subcommand execution. Semicolons may be repeated. When the multi
|
||||
button is pressed, each subcommand is 'pressed', and when the multi button
|
||||
is released each subcommand is 'released'.
|
||||
|
||||
There are also press-only multis, defined as "+{...}". These act just like
|
||||
regular multis, with two differences: the multi is only run when you press
|
||||
the button (release isignored), and each subcommand must be prefixed with
|
||||
'+' or '-' to indicate whether the the subcommand should be pressed or
|
||||
released.
|
||||
|
||||
For example: {Joypad1 A,Joypad2 A;Joypad3 A;;;;;QuickSave000}
|
||||
This presses (or releases) A on pads 1 and 2, then waits one frame, then
|
||||
presses A on pad 3, then waits 5 frames, then saves to snapshot 0 (on press
|
||||
only).
|
||||
|
||||
You may access the multi number in the returned s9xcommand_t structure as
|
||||
cmd.button.multi_idx. This may be used to assign the same multi to multiple
|
||||
buttons:
|
||||
MULTI#<num> ; NOTE: that's a literal octothorpe
|
339
docs/gpl-2.0.txt
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
504
docs/lgpl-2.1.txt
Normal file
@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
385
docs/porting.html
Normal file
@ -0,0 +1,385 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<meta name="description" content="How to Port Snes9x to a New Platform">
|
||||
<style type="text/css">
|
||||
<!-- ul { list-style-type:none } h2 { margin-top:3em } h3 { margin-top:2em } -->
|
||||
</style>
|
||||
<title>Porting Snes9x</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="text-align:center">How to Port Snes9x to a New Platform</h1>
|
||||
<div style="text-align:right">
|
||||
Version: 1.52<br>
|
||||
(c) Copyright 1998 Gary Henderson
|
||||
</div>
|
||||
<h2>Introduction</h2>
|
||||
<p>
|
||||
This is brief description of the steps to port Snes9x to the new platform. It describes what code you have to write and what functions exist that you can make use of. It also gives some insights as to how Snes9x actually works, although that will be subject of another document yet to be written.
|
||||
</p>
|
||||
<h2>System Requirements</h2>
|
||||
<p>
|
||||
A C++ compiler. For the most part Snes9x really isn't written in C++, it just uses the C++ compiler as a “better C” compiler to get inline functions and so on. GCC is good for compiling Snes9x (<a href="http://gcc.gnu.org/">http://gcc.gnu.org/</a>).
|
||||
</p>
|
||||
<p>
|
||||
A fast CPU. SNES emulation is very compute intensive; two, or sometimes three CPUs to emulate, an 8-channel 16-bit stereo sound digital signal processor with real-time sample decompression, filter and echo effects, two custom graphics processor chips that can produce transparency, scaling, rotation and window effects in 32768 colors, and finally hardware DMA all take their toll on the host CPU.
|
||||
</p>
|
||||
<p>
|
||||
Enough RAM. Snes9x uses 8MB to load SNES ROM images and several MB for emulating sound, graphics, custom chips, and so on.
|
||||
</p>
|
||||
<p>
|
||||
A 16-bit color (two bytes per pixel) or deeper display, at least 512*478 pixels in resolution. Pixel format conversion may be required before you place the rendered SNES screen on to the display.
|
||||
</p>
|
||||
<p>
|
||||
Sound output requires spooling 8-bit or 16-bit, mono or stereo digital sound data to the host sound system. Some ports can use interrupts or callbacks from the sound system to know when more sound data is required, most other ports have to periodically poll the host sound system to see if more data is required; if it is then the sound mixing code is called to fill the sound buffer with SNES sound data, which then can be passed on to the host sound system. Sound data is generated as an array of bytes (<code>uint8</code>) for 8-bit sound or shorts (<code>int16</code>) for 16-bit data. Stereo sound data generates twice as many samples, with each channel's samples interleaved, first left's then right's.
|
||||
</p>
|
||||
<p>
|
||||
For the user to be able to control and play SNES games, some form of input device is required, a joypad or keyboard, for example. The real SNES can have 2 eight-button digital joypads connected to it or 5 joypads when an optional multi-player adaptor is connected, although most games only require a single joypad. Access to all eight buttons and the direction pad, of course, are usually required by most games. Snes9x does emulate the multi-player adaptor hardware, if you were wondering, but its still up to you to provide the emulation of the individual joypads.
|
||||
</p>
|
||||
<p>
|
||||
The real SNES also has a SNES mouse, Super Scope and Justifier (light-gun) available as optional extras. Snes9x can emulate all of these using some form of pointing device, usually the host system's mouse.
|
||||
</p>
|
||||
<p>
|
||||
Some SNES game cartridges contains a small amount of extra RAM and a battery, so ROMs could save a player's progress through a game for games that takes many hours to play from start to finish. Snes9x simulates this S-RAM by saving the contents of the area of memory occupied by the S-RAM into a file then automatically restoring it again the next time the user plays the same game. If the hardware you're porting to doesn't have a storage media available then you could be in trouble.
|
||||
</p>
|
||||
<p>
|
||||
Snes9x also implements freeze-game files which can record the state of the SNES hardware and RAM at a particular point in time and can restore it to that exact state at a later date - the result is that users can save a game at any point, not just at save-game or password points provided by the original game coders. Each freeze file is over 400k in size. To help save disk space, Snes9x can be compiled with zlib (<a href="http://www.zlib.net/">http://www.zlib.net/</a>), which is used to GZIP compress the freeze files, reducing the size to typically below 100k. zlib is also used to load GZIP or ZIP compressed ROM images. Additionally, Snes9x supports JMA archives compressed with NSRT (<a href="http://nsrt.edgeemu.com/">http://nsrt.edgeemu.com/</a>).
|
||||
</p>
|
||||
<h2>Compile-Time Options</h2>
|
||||
<h3><code>DEBUGGER</code></h3>
|
||||
<p>
|
||||
Enables extra code to assist you in debugging SNES ROMs. The debugger has only ever been a quick-hack and user-interface to debugger facilities is virtually non-existent. Most of the debugger information is output via stdout and enabling the debugger slows the whole emulator down slightly. However, the debugger options available are very powerful; you could use it to help get your port working. You probably still want to ship the finished version with the debugger disabled, it will only confuse non-technical users.
|
||||
</p>
|
||||
<h3><code>RIGHTSHIFT_IS_SAR</code></h3>
|
||||
<p>
|
||||
Define this if your compiler uses shift right arithmetic for signed values. For example, GCC and Visual C++ use shift right arithmetic.
|
||||
</p>
|
||||
<h3><code>CPU_SHUTDOWN</code></h3>
|
||||
<p>
|
||||
This is a speed-up hack. When defined and if <code>Settings.ShutdownMaster</code> is <code>true</code>, Snes9x starts watching for when CPU is in a simply loop waiting for a known event to happen - like the end of the current scanline. If Snes9x spots CPU in such a loop, it simply skips the emulation of its instructions until the event happens. It can be a big win with lots of SNES games, but will break a small number of games. In this case, set <code>Settings.ShutdownMaster</code> to <code>false</code> before you load a ROM image. Note that this hack is forcibly disabled in some games. See <code>Memory.ApplyROMFixes</code> function for the list of such games.
|
||||
</p>
|
||||
<h3><code>CORRECT_VRAM_READS</code></h3>
|
||||
<p>
|
||||
You must define this. It allows correct VRAM reads.
|
||||
</p>
|
||||
<h3><code>ZLIB / UNZIP_SUPPORT / JMA_SUPPORT</code></h3>
|
||||
<p>
|
||||
Define these if you want to support GZIP/ZIP/JMA compressed ROM images and GZIP compressed freeze-game files.
|
||||
</p>
|
||||
<h3><code>ZSNES_FX / ZSNES_C4</code></h3>
|
||||
<p>
|
||||
Define these if your CPU is x86 compatible and you're going to use the ZSNES Super FX and C4 assembler codes.
|
||||
</p>
|
||||
<h3><code>USE_OPENGL</code></h3>
|
||||
<p>
|
||||
Define this and set <code>Settings.OpenGLEnable</code> to <code>true</code>, then you'll get the rendered SNES image as one OpenGL texture.
|
||||
</p>
|
||||
<h3>Typical Options Common for Most Platforms</h3>
|
||||
<p><code>
|
||||
ZLIB<br>
|
||||
UNZIP_SUPPORT<br>
|
||||
JMA_SUPPORT<br>
|
||||
CPU_SHUTDOWN<br>
|
||||
RIGHTSHIFT_IS_SAR<br>
|
||||
CORRECT_VRAM_READS
|
||||
</code></p>
|
||||
<h2>Editing port.h</h2>
|
||||
<p>
|
||||
You may need to edit <code>port.h</code> to fit Snes9x to your system.
|
||||
</p>
|
||||
<p>
|
||||
If the byte ordering of your system is least significant byte first, make sure <code>LSB_FIRST</code> is defined, otherwise make sure it's not defined.
|
||||
</p>
|
||||
<p>
|
||||
You'll need to make sure what pixel format your system uses for 16-bit colors (<code>RGB565</code>, <code>RGB555</code>, <code>BGR565</code> or <code>BGR555</code>), and if it's not <code>RGB565</code>, define <code>PIXEL_FORMAT</code> to it so that Snes9x will use it to render the SNES screen. For example, Windows uses <code>RGB565</code>, Mac OS X uses <code>RGB555</code>. If your system supports more than one pixel format, you can define <code>GFX_MULTI_FORMAT</code> and change Snes9x's pixel format dynamically by calling <code>S9xSetRenderPixelFormat</code> function. If your system is 24 or 32-bit only, then don't define anything; instead write a conversion routine that will take a complete rendered 16-bit SNES screen in <code>RGB565</code> format and convert to the format required to be displayed on your system.
|
||||
</p>
|
||||
<p>
|
||||
<code>port.h</code> also typedefs some types; <code>uint8</code> for an unsigned 8-bit quantity, <code>uint16</code> for an unsigned 16-bit quantity, <code>uint32</code> for a 32-bit unsigned quantity and <code>bool8</code> for a <code>true</code>/<code>false</code> type. Signed versions are also typedef'ed.
|
||||
</p>
|
||||
<h2>Controllers Management</h2>
|
||||
<p>
|
||||
Read <code>controls.h</code>, <code>crosshair.h</code>, <code>controls.txt</code> and <code>control-inputs.txt</code> for details. This section is the minimal explanation to get the SNES controls workable.
|
||||
</p>
|
||||
<p>
|
||||
The real SNES allows several different types of devices to be plugged into the game controller ports. The devices Snes9x emulates are a joypad, multi-player adaptor known as the Multi Player 5 or Multi Tap (allowing a further 4 joypads to be plugged in), a 2-button mouse, a light gun known as the Super Scope, and a light gun known as the Justifier.
|
||||
</p>
|
||||
<p>
|
||||
In your initialization code, call <code>S9xUnmapAllControl</code> function.
|
||||
</p>
|
||||
<p>
|
||||
Map any IDs to each SNES controller's buttons and pointers. (ID 249-255 are reserved).
|
||||
</p>
|
||||
<p>
|
||||
Typically, use <code>S9xMapPointer</code> function for the pointer of the SNES mouse, Super Scope and Justifier, <code>S9xMapButton</code> function for other buttons. Set <code>poll</code> to <code>false</code> for the joypad buttons, <code>true</code> for the other buttons and pointers.
|
||||
</p>
|
||||
<p>
|
||||
<code>S9xMapButton(k1P_A_Button, s9xcommand_t cmd = S9xGetCommandT("Joypad1 A"), false);</code>
|
||||
</p>
|
||||
<p>
|
||||
In your main emulation loop, after <code>S9xMainLoop</code> function is called, check your system's keyboard/joypad, and call <code>S9xReportButton</code> function to report the states of the SNES joypad buttons to Snes9x.
|
||||
</p>
|
||||
<p>
|
||||
<code>void MyMainLoop (void)<br>
|
||||
{<br>
|
||||
S9xMainLoop();<br>
|
||||
MyReportButttons();<br>
|
||||
}</code>
|
||||
</p>
|
||||
<p>
|
||||
<code>void MyReportButtons (void)<br>
|
||||
{<br>
|
||||
S9xReportButton(k1P_A_Button, (key_is_pressed ? true : false));<br>
|
||||
}</code>
|
||||
</p>
|
||||
<p>
|
||||
Prepare your <code>S9xPollButton</code> and <code>S9xPollPointer</code> function to reply Snes9x's request for other buttons/cursors states.
|
||||
</p>
|
||||
<p>
|
||||
Call <code>S9xSetController</code> function. It connects each input device to each SNES input port.<br>
|
||||
Here's typical controller settings that is used by the real SNES games:
|
||||
</p>
|
||||
<p>Joypad<br>
|
||||
<code>S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);<br>
|
||||
S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);</code>
|
||||
</p>
|
||||
<p>Mouse (port 1)<br>
|
||||
<code>S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0);<br>
|
||||
S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);</code>
|
||||
</p>
|
||||
<p>Mouse (port 2)<br>
|
||||
<code>S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);<br>
|
||||
S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0);</code>
|
||||
</p>
|
||||
<p>Super Scope<br>
|
||||
<code>S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);<br>
|
||||
S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0);</code>
|
||||
</p>
|
||||
<p>Multi Player 5<br>
|
||||
<code>S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);<br>
|
||||
S9xSetController(1, CTL_MP5, 1, 2, 3, 4);</code>
|
||||
</p>
|
||||
<p>Justifier<br>
|
||||
<code>S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);<br>
|
||||
S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0);</code>
|
||||
</p>
|
||||
<p>Justifier (2 players)<br>
|
||||
<code>S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);<br>
|
||||
S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0);</code>
|
||||
</p>
|
||||
<h2>Existing Interface Functions</h2>
|
||||
<h3><code>bool8 Memory.Init (void)</code></h3>
|
||||
<p>
|
||||
Allocates and initializes several major lumps of memory, for example the SNES ROM and RAM arrays, tile cache arrays, etc. Returns <code>false</code> if memory allocation fails.
|
||||
</p>
|
||||
<h3><code>void Memory.Deinit (void)</code></h3>
|
||||
<p>
|
||||
Deallocates the memory allocations made by <code>Memory.Init</code> function.
|
||||
</p>
|
||||
<h3><code>bool8 S9xGraphicsInit (void)</code></h3>
|
||||
<p>
|
||||
Allocates and initializes several lookup tables used to speed up SNES graphics rendering. Call after you have initialized the <code>GFX.Screen</code> and <code>GFX.Pitch</code> values. Returns <code>false</code> if memory allocation fails.
|
||||
</p>
|
||||
<h3><code>void S9xGraphicsDeinit (void)</code></h3>
|
||||
<p>
|
||||
Deallocates the memory allocations made by <code>S9xGraphicsInit</code> function.
|
||||
</p>
|
||||
<h3><code>bool8 S9xInitAPU (void)</code></h3>
|
||||
<p>
|
||||
Allocates and initializes several arrays used by the sound CPU and sound generation code. Returns <code>false</code> if memory allocation fails.
|
||||
</p>
|
||||
<h3><code>void S9xDeinitAPU (void)</code></h3>
|
||||
<p>
|
||||
Deallocates the allocations made by <code>S9xInitAPU</code> function.
|
||||
</p>
|
||||
<h3><code>bool8 S9xInitSound (int buffer_ms, int lag_ms)</code></h3>
|
||||
<p>
|
||||
Allocates memory for mixing and queueing SNES sound data, does more sound code initialization and opens the host system's sound device by calling <code>S9xOpenSoundDevice</code>, a function you must provide. Before calling this function you must set up <code>Settings.SoundSync</code>, <code>Settings.SixteenBitSound</code>, <code>Settings.SoundPlaybackRate</code>, <code>Settings.SoundInputRate</code> (see section below) and <code>Settings.Stereo</code>.<br>
|
||||
<code>buffer_ms</code>, given in milliseconds, is the memory buffer size for queueing sound data. <code>lag_ms</code> is allowable latency between when a sample is queued and when it is pulled in <code>S9xMixSamples</code>. Set <code>lag_ms</code> to zero if you have your own latency handling code in your port.
|
||||
</p>
|
||||
<h3><code>void S9xReset (void)</code></h3>
|
||||
<p>
|
||||
Resets the SNES emulated hardware back to the state it was in at “switch-on” except the S-RAM area is preserved (“hardware reset”). The effect is it resets the current game back to the start. This function is automatically called by <code>Memory.LoadROM</code> function.
|
||||
</p>
|
||||
<h3><code>void S9xSoftReset (void)</code></h3>
|
||||
<p>
|
||||
Similar to <code>S9xReset</code> function, but “software reset” as you press the SNES reset button.
|
||||
</p>
|
||||
<h3><code>bool8 Memory.LoadROM (const char *filepath)</code></h3>
|
||||
<p>
|
||||
Attempts to load the specified ROM image filename into the emulated ROM area. There are many different SNES ROM image formats and the code attempts to auto-detect as many different types as it can and in a vast majority of the cases gets it right.<br>
|
||||
There are several ROM image options in the <code>Settings</code>structure; allow the user to set them before calling <code>Memory.LoadROM</code> function, or make sure they are all reset to default values before each call to <code>Memory.LoadROM</code> function. See <code>Settings.ForceXXX</code> in <code>snes9x.h</code>.
|
||||
</p>
|
||||
<h3><code>bool8 Memory.LoadMultiCart (const char *cartApath, const char *cartBpath)</code></h3>
|
||||
<p>
|
||||
Attempts to load multiple ROM images into the emulated ROM area, for the multiple cartridge systems such as Sufami Turbo, Same Game, etc.
|
||||
</p>
|
||||
<h3><code>bool8 Memory.LoadSRAM (const char *filepath)</code></h3>
|
||||
<p>
|
||||
Call this function to load the associated S-RAM save file (if any). The filename should be based on the ROM image name to allow easy linkage. The current ports change the directory and the filename extension of the ROM filename to derive the S-RAM filename.
|
||||
</p>
|
||||
<h3><code>bool8 Memory.SaveSRAM (const char *filepath)</code></h3>
|
||||
<p>
|
||||
Call this function to save the emulated S-RAM area into a file so it can be restored again the next time the user wants to play the game. Remember to call this when just before the emulator exits or when the user has been playing a game and is about to load another one.
|
||||
</p>
|
||||
<h3><code>void S9xMainLoop (void)</code></h3>
|
||||
<p>
|
||||
The emulator main loop. Call this from your own main loop that calls this function (if a ROM image is loaded and the game is not paused), processes any pending host system events, then goes back around the loop again until the emulator exits. <code>S9xMainLoop</code> function normally returns control to your main loop once every emulated frame, when it reaches the start of scan-line zero. However it may take a few frames when a huge memory transfer is being emulated. The function can return more often if the <code>DEBUGGER</code> compile-time flag is defined and the CPU has hit a break point, or the <code>DEBUG_MODE_FLAG</code> bit is set in <code>CPU.Flags</code> or instruction single-stepping is enabled.
|
||||
</p>
|
||||
<h3><code>void S9xMixSamples (uint8 *buffer, int sample_count)</code></h3>
|
||||
<p>
|
||||
Call this function from your host sound system handling code to fill <code>buffer</code> with ready-mixed SNES sound data. If 16-bit sound mode is chosen, then the buffer will be filled with an array of <code>sample_count</code> <code>int16</code>, otherwise an array of <code>sample_count</code> <code>uint8</code>. If stereo sound generation is selected the buffer is filled with the same number of samples, but in pairs, first a left channel sample followed by the right channel sample.<br>
|
||||
If there are less queued samples than you request by <code>sample_count</code>, the function fills <code>buffer</code> with silent sound data and returns <code>false</code>. To avoid this shortage of queued samples, request larger buffer size when calling <code>S9xInitSound</code>, and handle sound latency safely.
|
||||
</p>
|
||||
<h3><code>int S9xGetSampleCount (void)</code></h3>
|
||||
<p>
|
||||
Returns the number of sound samples available in the buffer for your configured playback settings.
|
||||
</p>
|
||||
<h3><code>void S9xSetSamplesAvailableCallback (void (*) samples_available (void *), void *data)</code></h3>
|
||||
<p>
|
||||
Call this function to set up a callback that is run when sound samples are made available. <code>samples_available</code> is a function you provide that returns <code>void</code> and takes a pointer as an argument. <code>data</code> is a pointer that you may wish to pass to your callback or can be <code>NULL</code>. If you choose to provide a callback, you must call the provided <code>S9xFinalizeSamples</code> function inside it to actually buffer the samples. If you are using a callback-oriented sound API, it is recommended to set up a function that locks a common mutex during the calls to <code>S9xFinalizeSamples</code> and <code>S9xMixSamples</code> to prevent them from running at the same time and corrupting the sound buffer.<br>
|
||||
If you wish to disable a callback you have set up or need to temporarily shut down your sound system, you may pass <code>NULL</code> for both arguments to revert to the built-in version.
|
||||
</p>
|
||||
<h3><code>bool8 S9xSyncSound (void)</code></h3>
|
||||
<p>
|
||||
Call this function to synchronize the sound buffers to the game state. If Snes9x is generating too much sound data, or a buffer-overrun is likely, this function will return <code>false</code>. In this case, you may wish to wait until your host sound system uses the available samples, and <code>S9xSyncSound</code> returns <code>true</code> before continuing to execute <code>S9xMainLoop</code>.
|
||||
</p>
|
||||
<h3><code>bool8 S9xSetSoundMute (bool8 mute)</code></h3>
|
||||
<p>
|
||||
Call with a <code>true</code> parameter to prevent <code>S9xMixSamples</code> function from processing SNES sample data and instead just filling the return buffer with silent sound data. Useful if your sound system is interrupt or callback driven and the game has been paused either directly or indirectly because the user interacting with the emulator's user interface in some way.
|
||||
</p>
|
||||
<h3><code>bool8 S9xFreezeGame (const char *filepath)</code></h3>
|
||||
<p>
|
||||
Call this function to record the current SNES hardware state into a file, the file can be loaded back using <code>S9xUnfreezeGame</code> function at a later date effectively restoring the current game to exact same spot. Call this function while you're processing any pending system events when <code>S9xMainLoop</code> function has returned control to you in your main loop.
|
||||
</p>
|
||||
<h3><code>bool8 S9xUnfreezeGame (const char *filepath)</code></h3>
|
||||
<p>
|
||||
Restore the SNES hardware back to the exactly the state it was in when <code>S9xFreezeGame</code> function was used to generate the file specified. You have to arrange the correct ROM is already loaded using <code>Memory.LoadROM</code> function, an easy way to arrange this is to base freeze-game filenames on the ROM image name. The UNIX/Linux ports load freeze-game files when the user presses a function key, with the names romfilename.000 for F1, romfilename.001 for F2, etc. Games are frozen in the first place when the user presses Shift-function key. You could choose some other scheme.
|
||||
</p>
|
||||
<h3><code>void S9xDumpSPCSnapshot (void)</code></h3>
|
||||
<p>
|
||||
Call this funtion to make a so-called SPC file, a snapshot of SNES sound state. Actual dump occurs at the first key-on event after this function is called.
|
||||
</p>
|
||||
<h3><code>void S9xSetInfoString (const char *string)</code></h3>
|
||||
<p>
|
||||
Call this function if you want to show a message onto the SNES screen.
|
||||
</p>
|
||||
<h3>Other Available Functions</h3>
|
||||
<p>
|
||||
See <code>movie.h</code> and <code>movie.cpp</code> to support the Snes9x movie feature.<br>
|
||||
See <code>cheats.h</code>, <code>cheats.cpp</code> and <code>cheats2.cpp</code> to support the cheat feature.
|
||||
</p>
|
||||
<h2>Interface Functions You Need to Implement</h2>
|
||||
<h3><code>bool8 S9xOpenSnapshotFile (const char *filepath, bool8 read_only, STREAM *file)</code></h3>
|
||||
<p>
|
||||
This function opens a freeze-game file. <code>STREAM</code> is defined as a <code>gzFile</code> if <code>ZLIB</code> is defined else it's defined as <code>FILE *</code>. The <code>read_only</code> parameter is set to <code>true</code> when reading a freeze-game file and <code>false</code> when writing a freeze-game file. Open the file <code>filepath</code> and return its pointer <code>file</code>.
|
||||
</p>
|
||||
<h3><code>void S9xCloseSnapshotFile (STREAM file)</code></h3>
|
||||
<p>
|
||||
This function closes the freeze-game file opened by <code>S9xOpenSnapshotFile</code> function.
|
||||
</p>
|
||||
<h3><code>void S9xExit (void)</code></h3>
|
||||
<p>
|
||||
Called when some fatal error situation arises or when the “q” debugger command is used.
|
||||
</p>
|
||||
<h3><code>bool8 S9xInitUpdate (void)</code></h3>
|
||||
<p>
|
||||
Called just before Snes9x begins to render an SNES screen. Use this function if you should prepare before drawing, otherwise let it empty.
|
||||
</p>
|
||||
<h3><code>bool8 S9xDeinitUpdate (int width, int height)</code></h3>
|
||||
<p>
|
||||
Called once a complete SNES screen has been rendered into the <code>GFX.Screen</code> memory buffer, now is your chance to copy the SNES rendered screen to the host computer's screen memory. The problem is that you have to cope with different sized SNES rendered screens: 256*224, 256*239, 512*224, 512*239, 512*448 and 512*478.
|
||||
</p>
|
||||
<h3><code>void S9xMessage (int type, int number, const char *message)</code></h3>
|
||||
<p>
|
||||
When Snes9x wants to display an error, information or warning message, it calls this function. Check in <code>messages.h</code> for the types and individual message numbers that Snes9x currently passes as parameters.<br>
|
||||
The idea is display the message string so the user can see it, but you choose not to display anything at all, or change the message based on the message number or message type.<br>
|
||||
Eventually all debug output will also go via this function, trace information already does.
|
||||
</p>
|
||||
<h3><code>bool8 S9xOpenSoundDevice (void)</code></h3>
|
||||
<p>
|
||||
<code>S9xInitSound</code> function calls this function to actually open the host sound device.
|
||||
</p>
|
||||
<h3><code>const char *S9xGetFilename (const char *extension, enum s9x_getdirtype dirtype)</code></h3>
|
||||
<p>
|
||||
When Snes9x needs to know the name of the cheat/IPS file and so on, this function is called. Check <code>extension</code> and <code>dirtype</code>, and return the appropriate filename. The current ports return the ROM file path with the given extension.
|
||||
</p>
|
||||
<h3><code>const char *S9xGetFilenameInc (const char *extension, enum s9x_getdirtype dirtype)</code></h3>
|
||||
<p>
|
||||
Almost the same as <code>S9xGetFilename</code> function, but used for saving SPC files etc. So you have to take care not to delete the previously saved file, by increasing the number of the filename; romname.000.spc, romname.001.spc, ...
|
||||
</p>
|
||||
<h3><code>const char *S9xGetDirectory (enum s9x_getdirtype dirtype)</code></h3>
|
||||
<p>
|
||||
Called when Snes9x wants to know the directory <code>dirtype</code>.
|
||||
</p>
|
||||
<h3><code>const char *S9xChooseFilename (bool8 read_only)</code></h3>
|
||||
<p>
|
||||
If your port can match Snes9x's built-in <code>LoadFreezeFile</code>/<code>SaveFreezeFile</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>.
|
||||
</p>
|
||||
<h3><code>const char *S9xChooseMovieFilename (bool8 read_only)</code></h3>
|
||||
<p>
|
||||
If your port can match Snes9x's built-in <code>BeginRecordingMovie</code>/<code>LoadMovie</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>.
|
||||
</p>
|
||||
<h3><code>const char *S9xBasename (const char *path)</code></h3>
|
||||
<p>
|
||||
Called when Snes9x wants to know the name of the ROM image. Typically, extract the filename from <code>path</code> and return it.
|
||||
</p>
|
||||
<h3><code>void S9xAutoSaveSRAM (void)</code></h3>
|
||||
<p>
|
||||
If <code>Settings.AutoSaveDelay</code> is not zero, Snes9x calls this function when the contents of the S-RAM has been changed. Typically, call <code>Memory.SaveSRAM</code> function from this function.
|
||||
</p>
|
||||
<h3><code>void S9xToggleSoundChannel (int c)</code></h3>
|
||||
<p>
|
||||
If your port can match Snes9x's built-in <code>SoundChannelXXX</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>. Basically, turn on/off the sound channel <code>c</code> (0-7), and turn on all channels if <code>c</code> is 8.
|
||||
</p>
|
||||
<h3><code>void S9xSetPalette (void)</code></h3>
|
||||
<p>
|
||||
Called when the SNES color palette has changed. Use this function if your system should change its color palette to match the SNES's. Otherwise let it empty.
|
||||
</p>
|
||||
<h3><code>void S9xSyncSpeed (void)</code></h3>
|
||||
<p>
|
||||
Called at the end of <code>S9xMainLoop</code> function, when emulating one frame has been done. You should adjust the frame rate in this function.
|
||||
</p>
|
||||
<h2>Global Variables</h2>
|
||||
<h3><code>uint16 *GFX.Screen</code></h3>
|
||||
<p>
|
||||
A <code>uint16</code> array pointer to (at least) 2*512*478 bytes buffer where Snes9x puts the rendered SNES screen. However, if your port will not support hires mode (<code>Settings.SupportHiRes = false</code>), then a 2*256*239 bytes buffer is allowed. You should allocate the space by yourself. As well you can change the <code>GFX.Screen</code> value after <code>S9xDeinitUpdate</code> function is called so that double-buffering will be easy.
|
||||
</p>
|
||||
<h3><code>uint32 GFX.Pitch</code></h3>
|
||||
<p>
|
||||
Bytes per line (not pixels per line) of the <code>GFX.Screen</code> buffer. Typically set it to 1024. When the SNES screen is 256 pixels width and <code>Settings.OpenGLEnable</code> is <code>false</code>, last half 512 bytes per line are unused. When <code>Settings.OpenGLEnable</code> is <code>true</code>, <code>GFX.Pitch</code> is ignored.
|
||||
</p>
|
||||
<h3>Settings structure</h3>
|
||||
<p>
|
||||
There are various switches in the <code>Settings</code> structure. See <code>snes9x.h</code> for details. At least the settings below are required for good emulation.
|
||||
</p>
|
||||
<p><code>
|
||||
memset(&Settings, 0, sizeof(Settings));<br>
|
||||
Settings.MouseMaster = true;<br>
|
||||
Settings.SuperScopeMaster = true;<br>
|
||||
Settings.JustifierMaster = true;<br>
|
||||
Settings.MultiPlayer5Master = true;<br>
|
||||
Settings.FrameTimePAL = 20000;<br>
|
||||
Settings.FrameTimeNTSC = 16667;<br>
|
||||
Settings.SixteenBitSound = true;<br>
|
||||
Settings.Stereo = true;<br>
|
||||
Settings.SoundPlaybackRate = 32000;<br>
|
||||
Settings.SoundInputRate = 32000;<br>
|
||||
Settings.SupportHiRes = true;<br>
|
||||
Settings.Transparency = true;<br>
|
||||
Settings.AutoDisplayMessages = true;<br>
|
||||
Settings.InitialInfoStringTimeout = 120;<br>
|
||||
Settings.HDMATimingHack = 100;<br>
|
||||
Settings.BlockInvalidVRAMAccessMaster = true;
|
||||
</code></p>
|
||||
<h3><code>Settings.SoundInputRate</code></h3>
|
||||
<p>
|
||||
Adjusts the sound rate through resampling. For every <code>Settings.SoundInputRate</code> samples generated by the SNES, <code>Settings.SoundPlaybackRate</code> samples will be produced.<br>
|
||||
The sound generation rate on a SNES is directly proportional to the video output rate. Displays that synchronize with the vertical refresh but have a slightly lower refresh-rate than the emulated system can experience sound drop-outs. It may be beneficial to provide an option for users to configure <code>Settings.SoundInputRate</code> to suit their own systems. Setting <code>Settings.SoundInputRate</code> to a value that matches the actual output rate (i.e. 31977hz for 59.96hz) or lower will allow the users to eliminate crackling. A range of 31000hz to 33000hz should be inclusive enough for all displays. Use of this setting paired with the <code>S9xSyncSound</code> function can eliminate sound discontinuity.
|
||||
</p>
|
||||
<div style="text-align:right; margin-top:3em">
|
||||
Updated most recently by: 2009/12/20 zones
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
84
docs/snapshots.txt
Normal file
@ -0,0 +1,84 @@
|
||||
***** Important notice ********************************************************
|
||||
This document describes the snapshot file format for Snes9x 1.52 and later,
|
||||
not compatible with 1.51.
|
||||
*******************************************************************************
|
||||
|
||||
Snes9x snapshot file format: (may be gzip-compressed)
|
||||
|
||||
Begins with fixed length signature, consisting of a string, ':', a 4-digit
|
||||
decimal version, and a '\n'.
|
||||
|
||||
#!s9xsnp:0006 <-- '\n' after the 6
|
||||
|
||||
Then we have various blocks. The block format is: 3-character block name,
|
||||
':', 6-digit length, ':', then the data. Blocks are written in a defined
|
||||
order. Structs are written packed with their members in a defined order, in
|
||||
big-endian order where applicable.
|
||||
|
||||
NAM:000019:Chrono Trigger.zip
|
||||
|
||||
Currently defined blocks (in order) are:
|
||||
|
||||
Essential parts:
|
||||
NAM - ROM filename, from Memory.ROMFilename. 0-terminated string.
|
||||
CPU - struct SCPUState, CPU internal state variables.
|
||||
REG - struct SRegisters, emulated CPU registers.
|
||||
PPU - struct SPPU, PPU internal variables. Note that IPPU is never saved.
|
||||
DMA - struct SDMA, DMA/HDMA state variables.
|
||||
VRA - Memory.VRAM, 0x10000 bytes.
|
||||
RAM - Memory.RAM, 0x20000 bytes (WRAM).
|
||||
SRA - Memory.SRAM, 0x20000 bytes.
|
||||
FIL - Memory.FillRAM, 0x8000 bytes (register backing store).
|
||||
SND - All of sound emulated registers and state valiables.
|
||||
CTL - struct SControlSnapshot, controller emulation.
|
||||
TIM - struct STimings, variables about timings between emulated events.
|
||||
|
||||
Optional parts:
|
||||
SFX - struct FxRegs_s, Super FX.
|
||||
SA1 - struct SSA1, SA1 internal state variables.
|
||||
SAR - struct SSA1Registers, SA1 emulated registers.
|
||||
DP1 - struct SDSP1, DSP-1.
|
||||
DP2 - struct SDSP2, DSP-2.
|
||||
DP4 - struct SDSP4, DSP-4.
|
||||
CX4 - Memory.C4RAM, 0x2000 bytes.
|
||||
ST0 - struct SST010, ST-010.
|
||||
OBC - struct SOBC1, OBC1 internal state variables.
|
||||
OBM - Memory.OBC1RAM, 0x2000 byts.
|
||||
S71 - struct SSPC7110Snapshot, SPC7110.
|
||||
SRT - struct SSRTCSnapshot, S-RTC internal state variables.
|
||||
CLK - struct SRTCData, S-RTC emulated registers.
|
||||
BSX - struct SBSX, BS-X.
|
||||
SHO - rendered SNES screen.
|
||||
MOV - struct SnapshotMovieInfo.
|
||||
MID - Some block of data the movie subsystem.
|
||||
|
||||
==================
|
||||
|
||||
Without changing the snapshot version number:
|
||||
---------------------------------------------
|
||||
|
||||
Blocks may be safely added at the END of the file, as anything after the last
|
||||
block is ignored. Blocks may not be moved or removed.
|
||||
|
||||
Blocks may not decrease in size. Say you decrease from 10 bytes to 5. Then
|
||||
later you increase back to 8. The only way you could safely do this is if
|
||||
bytes 5-7 still mean the same thing they meant when the block was 10 bytes
|
||||
long.
|
||||
|
||||
Blocks may increase in size as you wish, as long as you can handle old
|
||||
savestates with the old shorter size.
|
||||
|
||||
Struct members may not change in interpretation. New struct members may be
|
||||
added (at the END!) only if you can cope with them being binary-0 in older
|
||||
savestates. Struct members may not be removed or changed in size/type.
|
||||
|
||||
With changing the snapshot version number:
|
||||
------------------------------------------
|
||||
|
||||
Blocks may be added, moved, or removed at will.
|
||||
|
||||
Blocks may decrease in size.
|
||||
|
||||
Struct members may be added, moved, or deleted, and their
|
||||
interpretations/types may be changed. Use the 'debuted_in' and 'deleted_in'
|
||||
fields to indicate when the new member debuted or the old member went away.
|
173
docs/snes9x-license.txt
Normal file
@ -0,0 +1,173 @@
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
|
||||
(c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com),
|
||||
Jerremy Koot (jkoot@snes9x.com)
|
||||
|
||||
(c) Copyright 2002 - 2004 Matthew Kendora
|
||||
|
||||
(c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
|
||||
|
||||
(c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
|
||||
|
||||
(c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
|
||||
|
||||
(c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca),
|
||||
Kris Bleakley (codeviolation@hotmail.com)
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
OV2
|
||||
|
||||
|
||||
BS-X C emulator code
|
||||
(c) Copyright 2005 - 2006 Dreamer Nom,
|
||||
zones
|
||||
|
||||
C4 x86 assembler and some C emulation code
|
||||
(c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
|
||||
Nach,
|
||||
zsKnight (zsknight@zsnes.com)
|
||||
|
||||
C4 C++ code
|
||||
(c) Copyright 2003 - 2006 Brad Jorsch,
|
||||
Nach
|
||||
|
||||
DSP-1 emulator code
|
||||
(c) Copyright 1998 - 2006 _Demo_,
|
||||
Andreas Naive (andreasnaive@gmail.com),
|
||||
Gary Henderson,
|
||||
Ivar (ivar@snes9x.com),
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
neviksti (neviksti@hotmail.com)
|
||||
|
||||
DSP-2 emulator code
|
||||
(c) Copyright 2003 John Weidman,
|
||||
Kris Bleakley,
|
||||
Lord Nightmare (lord_nightmare@users.sourceforge.net),
|
||||
Matthew Kendora,
|
||||
neviksti
|
||||
|
||||
DSP-3 emulator code
|
||||
(c) Copyright 2003 - 2006 John Weidman,
|
||||
Kris Bleakley,
|
||||
Lancer,
|
||||
z80 gaiden
|
||||
|
||||
DSP-4 emulator code
|
||||
(c) Copyright 2004 - 2006 Dreamer Nom,
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Nach,
|
||||
z80 gaiden
|
||||
|
||||
OBC1 emulator code
|
||||
(c) Copyright 2001 - 2004 zsKnight,
|
||||
pagefault (pagefault@zsnes.com),
|
||||
Kris Bleakley
|
||||
Ported from x86 assembler to C by sanmaiwashi
|
||||
|
||||
SPC7110 and RTC C++ emulator code used in 1.39-1.51
|
||||
(c) Copyright 2002 Matthew Kendora with research by
|
||||
zsKnight,
|
||||
John Weidman,
|
||||
Dark Force
|
||||
|
||||
SPC7110 and RTC C++ emulator code used in 1.52+
|
||||
(c) Copyright 2009 byuu,
|
||||
neviksti
|
||||
|
||||
S-DD1 C emulator code
|
||||
(c) Copyright 2003 Brad Jorsch with research by
|
||||
Andreas Naive,
|
||||
John Weidman
|
||||
|
||||
S-RTC C emulator code
|
||||
(c) Copyright 2001 - 2006 byuu,
|
||||
John Weidman
|
||||
|
||||
ST010 C++ emulator code
|
||||
(c) Copyright 2003 Feather,
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Matthew Kendora
|
||||
|
||||
Super FX x86 assembler emulator code
|
||||
(c) Copyright 1998 - 2003 _Demo_,
|
||||
pagefault,
|
||||
zsKnight
|
||||
|
||||
Super FX C emulator code
|
||||
(c) Copyright 1997 - 1999 Ivar,
|
||||
Gary Henderson,
|
||||
John Weidman
|
||||
|
||||
Sound emulator code used in 1.5-1.51
|
||||
(c) Copyright 1998 - 2003 Brad Martin
|
||||
(c) Copyright 1998 - 2006 Charles Bilyue'
|
||||
|
||||
Sound emulator code used in 1.52+
|
||||
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
|
||||
|
||||
SH assembler code partly based on x86 assembler code
|
||||
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
|
||||
|
||||
2xSaI filter
|
||||
(c) Copyright 1999 - 2001 Derek Liauw Kie Fa
|
||||
|
||||
HQ2x, HQ3x, HQ4x filters
|
||||
(c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
|
||||
|
||||
NTSC filter
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
funkyass,
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
|
||||
|
||||
Specific ports contains the works of other authors. See headers in
|
||||
individual files.
|
||||
|
||||
|
||||
Snes9x homepage: http://www.snes9x.com/
|
||||
|
||||
Permission to use, copy, modify and/or distribute Snes9x in both binary
|
||||
and source form, for non-commercial purposes, is hereby granted without
|
||||
fee, providing that this license information and copyright notice appear
|
||||
with all copies and any derived work.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event shall the authors be held liable for any damages
|
||||
arising from the use of this software or it's derivatives.
|
||||
|
||||
Snes9x is freeware for PERSONAL USE only. Commercial users should
|
||||
seek permission of the copyright holders first. Commercial use includes,
|
||||
but is not limited to, charging money for Snes9x or software derived from
|
||||
Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
|
||||
using Snes9x as a promotion for your commercial product.
|
||||
|
||||
The copyright holders request that bug fixes and improvements to the code
|
||||
should be forwarded to them so everyone can benefit from the modifications
|
||||
in future versions.
|
||||
|
||||
Super NES and Super Nintendo Entertainment System are trademarks of
|
||||
Nintendo Co., Limited and its subsidiary companies.
|
241
docs/snes9x.conf.default
Normal file
@ -0,0 +1,241 @@
|
||||
#-----------------------------------------
|
||||
# snes9x.conf : Snes9x Configuration file
|
||||
#-----------------------------------------
|
||||
|
||||
[ROM]
|
||||
# Filename =
|
||||
LoROM = FALSE
|
||||
HiROM = FALSE
|
||||
PAL = FALSE
|
||||
NTSC = FALSE
|
||||
# Header = TRUE/FALSE to ForceHeader or ForceNoHeader
|
||||
# Interleaved = TRUE/FALSE to ForceInterleaved or ForceNoInterleaved
|
||||
Interleaved2 = FALSE
|
||||
InterleaveGD24 = FALSE
|
||||
Cheat = FALSE
|
||||
Patch = TRUE
|
||||
|
||||
[Sound]
|
||||
Sync = FALSE
|
||||
16BitSound = TRUE
|
||||
Stereo = TRUE
|
||||
ReverseStereo = FALSE
|
||||
Rate = 32000
|
||||
InputRate = 32000
|
||||
Mute = FALSE
|
||||
|
||||
[Display]
|
||||
HiRes = TRUE
|
||||
Transparency = TRUE
|
||||
GraphicWindows = TRUE
|
||||
DisplayFrameRate = FALSE
|
||||
DisplayWatchedAddresses = FALSE
|
||||
DisplayInput = FALSE
|
||||
DisplayFrameCount = FALSE
|
||||
MessagesInImage = TRUE
|
||||
MessageDisplayTime = 120
|
||||
|
||||
[Settings]
|
||||
BSXBootup = FALSE
|
||||
# FrameTime =
|
||||
FrameSkip = Auto
|
||||
TurboMode = FALSE
|
||||
TurboFrameSkip = 15
|
||||
MovieTruncateAtEnd = FALSE
|
||||
MovieNotifyIgnored = FALSE
|
||||
WrongMovieStateProtection = TRUE
|
||||
StretchScreenshots = 1
|
||||
SnapshotScreenshots = TRUE
|
||||
DontSaveOopsSnapshot = FALSE
|
||||
AutoSaveDelay = 0
|
||||
|
||||
[Controls]
|
||||
MouseMaster = TRUE
|
||||
SuperscopeMaster = TRUE
|
||||
JustifierMaster = TRUE
|
||||
MP5Master = TRUE
|
||||
AllowLeftRight = FALSE
|
||||
Port1 = pad1
|
||||
Port2 = none
|
||||
Mouse1Crosshair = 1 White/Black
|
||||
Mouse2Crosshair = 1 White/Black
|
||||
SuperscopeCrosshair = 2 White/Black
|
||||
Justifier1Crosshair = 4 Blue/Black
|
||||
Justifier2Crosshair = 4 MagicPink/Black
|
||||
|
||||
[Hack]
|
||||
EnableGameSpecificHacks = TRUE
|
||||
AllowInvalidVRAMAccess = FALSE
|
||||
SpeedHacks = FALSE
|
||||
DisableIRQ = FALSE
|
||||
DisableHDMA = FALSE
|
||||
HDMATiming = 100
|
||||
|
||||
[Netplay]
|
||||
Enable = FALSE
|
||||
Port = 6096
|
||||
Server = ""
|
||||
|
||||
[DEBUG]
|
||||
Debugger = FALSE
|
||||
Trace = FALSE
|
||||
|
||||
[Unix]
|
||||
# BaseDir = ~/.snes9x
|
||||
# SnapshotFilename =
|
||||
# PlayMovieFilename =
|
||||
# RecordMovieFilename =
|
||||
EnableGamePad = TRUE
|
||||
PadDevice1 = (null)
|
||||
PadDevice2 = (null)
|
||||
PadDevice3 = (null)
|
||||
PadDevice4 = (null)
|
||||
PadDevice5 = (null)
|
||||
PadDevice6 = (null)
|
||||
PadDevice7 = (null)
|
||||
PadDevice8 = (null)
|
||||
ThreadSound = FALSE
|
||||
SoundBufferSize = 100
|
||||
SoundFragmentSize = 2048
|
||||
# SoundDevice =
|
||||
ClearAllControls = FALSE
|
||||
|
||||
[Unix/X11]
|
||||
SetKeyRepeat = TRUE
|
||||
VideoMode = 1
|
||||
|
||||
[Unix/X11 Controls]
|
||||
J00:Axis1 = Joypad1 Axis Up/Down T=50%
|
||||
J00:Axis0 = Joypad1 Axis Left/Right T=50%
|
||||
J00:B1 = Joypad1 A
|
||||
J00:B2 = Joypad1 B
|
||||
J00:B0 = Joypad1 X
|
||||
J00:B3 = Joypad1 Y
|
||||
J00:B6 = Joypad1 L
|
||||
J00:B7 = Joypad1 R
|
||||
J00:B8 = Joypad1 Select
|
||||
J00:B11 = Joypad1 Start
|
||||
K00:u = Joypad1 Up
|
||||
K00:Up = Joypad1 Up
|
||||
K00:j = Joypad1 Down
|
||||
K00:n = Joypad1 Down
|
||||
K00:Down = Joypad1 Down
|
||||
K00:h = Joypad1 Left
|
||||
K00:Left = Joypad1 Left
|
||||
K00:k = Joypad1 Right
|
||||
K00:Right = Joypad1 Right
|
||||
K00:d = Joypad1 A
|
||||
K00:S+d = Joypad1 ToggleTurbo A
|
||||
K00:C+d = Joypad1 ToggleSticky A
|
||||
K00:c = Joypad1 B
|
||||
K00:S+c = Joypad1 ToggleTurbo B
|
||||
K00:C+c = Joypad1 ToggleSticky B
|
||||
K00:s = Joypad1 X
|
||||
K00:S+s = Joypad1 ToggleTurbo X
|
||||
K00:C+s = Joypad1 ToggleSticky X
|
||||
K00:x = Joypad1 Y
|
||||
K00:S+x = Joypad1 ToggleTurbo Y
|
||||
K00:C+x = Joypad1 ToggleSticky Y
|
||||
K00:a = Joypad1 L
|
||||
K00:v = Joypad1 L
|
||||
K00:S+a = Joypad1 ToggleTurbo L
|
||||
K00:S+v = Joypad1 ToggleTurbo L
|
||||
K00:C+a = Joypad1 ToggleSticky L
|
||||
K00:C+v = Joypad1 ToggleSticky L
|
||||
K00:z = Joypad1 R
|
||||
K00:S+z = Joypad1 ToggleTurbo R
|
||||
K00:C+z = Joypad1 ToggleSticky R
|
||||
K00:space = Joypad1 Select
|
||||
K00:Return = Joypad1 Start
|
||||
K00:KP_Up = Joypad2 Up
|
||||
K00:KP_Down = Joypad2 Down
|
||||
K00:KP_Left = Joypad2 Left
|
||||
K00:KP_Right = Joypad2 Right
|
||||
K00:Prior = Joypad2 A
|
||||
K00:Next = Joypad2 B
|
||||
K00:Home = Joypad2 X
|
||||
K00:End = Joypad2 Y
|
||||
K00:Insert = Joypad2 L
|
||||
K00:Delete = Joypad2 R
|
||||
K00:KP_Add = Joypad2 Select
|
||||
K00:KP_Enter = Joypad2 Start
|
||||
K00:Escape = ExitEmu
|
||||
K00:Pause = Pause
|
||||
K00:Scroll_Lock = Pause
|
||||
K00:CS+Escape = Reset
|
||||
K00:S+Escape = SoftReset
|
||||
K00:F12 = SaveFreezeFile
|
||||
K00:A+F3 = SaveFreezeFile
|
||||
K00:C+F3 = SaveFreezeFile
|
||||
K00:F11 = LoadFreezeFile
|
||||
K00:A+F2 = LoadFreezeFile
|
||||
K00:C+F2 = LoadFreezeFile
|
||||
K00:S+F1 = QuickSave000
|
||||
K00:S+F2 = QuickSave001
|
||||
K00:S+F3 = QuickSave002
|
||||
K00:S+F4 = QuickSave003
|
||||
K00:S+F5 = QuickSave004
|
||||
K00:S+F6 = QuickSave005
|
||||
K00:S+F7 = QuickSave006
|
||||
K00:S+F8 = QuickSave007
|
||||
K00:S+F9 = QuickSave008
|
||||
K00:F1 = QuickLoad000
|
||||
K00:F2 = QuickLoad001
|
||||
K00:F3 = QuickLoad002
|
||||
K00:F4 = QuickLoad003
|
||||
K00:F5 = QuickLoad004
|
||||
K00:F6 = QuickLoad005
|
||||
K00:F7 = QuickLoad006
|
||||
K00:F8 = QuickLoad007
|
||||
K00:F9 = QuickLoad008
|
||||
K00:F10 = LoadOopsFile
|
||||
K00:A+F1 = SaveSPC
|
||||
K00:C+F1 = SaveSPC
|
||||
K00:Print = Screenshot
|
||||
K00:S+1 = BeginRecordingMovie
|
||||
K00:S+2 = EndRecordingMovie
|
||||
K00:S+3 = LoadMovie
|
||||
K00:Tab = EmuTurbo
|
||||
K00:S+Tab = ToggleEmuTurbo
|
||||
K00:equal = IncFrameRate
|
||||
K00:minus = DecFrameRate
|
||||
K00:S+equal = IncFrameTime
|
||||
K00:S+minus = DecFrameTime
|
||||
K00:A+equal = IncEmuTurbo
|
||||
K00:A+minus = DecEmuTurbo
|
||||
K00:C+equal = IncTurboSpeed
|
||||
K00:C+minus = DecTurboSpeed
|
||||
K00:6 = SwapJoypads
|
||||
K00:A+F4 = SoundChannel0
|
||||
K00:C+F4 = SoundChannel0
|
||||
K00:A+F5 = SoundChannel1
|
||||
K00:C+F5 = SoundChannel1
|
||||
K00:A+F6 = SoundChannel2
|
||||
K00:C+F6 = SoundChannel2
|
||||
K00:A+F7 = SoundChannel3
|
||||
K00:C+F7 = SoundChannel3
|
||||
K00:A+F8 = SoundChannel4
|
||||
K00:C+F8 = SoundChannel4
|
||||
K00:A+F9 = SoundChannel5
|
||||
K00:C+F9 = SoundChannel5
|
||||
K00:A+F10 = SoundChannel6
|
||||
K00:C+F10 = SoundChannel6
|
||||
K00:A+F11 = SoundChannel7
|
||||
K00:C+F11 = SoundChannel7
|
||||
K00:A+F12 = SoundChannelsOn
|
||||
K00:C+F12 = SoundChannelsOn
|
||||
K00:1 = ToggleBG0
|
||||
K00:2 = ToggleBG1
|
||||
K00:3 = ToggleBG2
|
||||
K00:4 = ToggleBG3
|
||||
K00:5 = ToggleSprites
|
||||
K00:9 = ToggleTransparency
|
||||
K00:BackSpace = ClipWindows
|
||||
K00:0 = ToggleHDMA
|
||||
K00:A+Escape = Debugger
|
||||
M00:Pointer = Pointer Mouse1+Superscope+Justifier1
|
||||
M00:B0 = {Mouse1 L,Superscope Fire,Justifier1 Trigger}
|
||||
M00:B2 = {Mouse1 R,Superscope Cursor,Justifier1 Start}
|
||||
M00:B1 = {Justifier1 AimOffscreen Trigger,Superscope AimOffscreen}
|
||||
K00:grave = Superscope ToggleTurbo
|
||||
K00:slash = Superscope Pause
|
44
eboot-launcher/main.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#include <sys/return_code.h>
|
||||
#include <sys/process.h>
|
||||
#include <sys/memory.h>
|
||||
#include <sys/timer.h>
|
||||
#include <sys/paths.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <cell/sysmodule.h>
|
||||
#include <cell/cell_fs.h>
|
||||
#include <sysutil/sysutil_sysparam.h>
|
||||
//#include <sysutil/sysutil_discgame.h>
|
||||
#include <sysutil/sysutil_common.h>
|
||||
|
||||
SYS_PROCESS_PARAM(1001, 0x100000)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void) argc;
|
||||
char tn[128];
|
||||
char filename[128];
|
||||
|
||||
sprintf(tn, "%s", argv[0]);
|
||||
char *pch=tn;
|
||||
char *pathpos=strrchr(pch,'/');
|
||||
pathpos[0]=0;
|
||||
|
||||
sprintf(filename, "%s/RELOAD.SELF", tn);
|
||||
sys_game_process_exitspawn2(filename, NULL, NULL, NULL, 0, 1001, SYS_PROCESS_PRIMARY_STACK_SIZE_1M);
|
||||
}
|
||||
|
||||
|
BIN
pkg/ICON0.PNG
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
pkg/PARAM.SFO
Executable file
BIN
pkg/PIC1.PNG
Normal file
After Width: | Height: | Size: 1.3 MiB |
0
pkg/USRDIR/.empty
Normal file
BIN
pkg/USRDIR/borders/Centered-1080p/chrono-trigger.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
pkg/USRDIR/borders/Centered-1080p/ff6-dissidia.png
Normal file
After Width: | Height: | Size: 2.5 MiB |
BIN
pkg/USRDIR/borders/Centered-1080p/overlays/none-overlay.png
Normal file
After Width: | Height: | Size: 2.8 MiB |
BIN
pkg/USRDIR/borders/Centered-1080p/super-castlevania-4.png
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
pkg/USRDIR/borders/Centered-1080p/super-metroid.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
pkg/USRDIR/borders/Left-Portrait-1080p/chrono-trigger-schala.png
Normal file
After Width: | Height: | Size: 612 KiB |
After Width: | Height: | Size: 884 KiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 1.6 MiB |
BIN
pkg/USRDIR/borders/Left-Portrait-1080p/tactics-ogre.png
Normal file
After Width: | Height: | Size: 2.4 MiB |
BIN
pkg/USRDIR/borders/Menu/main-menu.jpg
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
pkg/USRDIR/gameaware/manual-reader/manual-reader-border.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
43
pkg/USRDIR/gameaware/manual-reader/manual-reader.cfg
Normal file
@ -0,0 +1,43 @@
|
||||
shaders = 1
|
||||
shader0 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/manualshaders/manual-reader.cg"
|
||||
|
||||
filter_linear0 = true
|
||||
|
||||
imports = "press_count_l;press_time_l;press_time_prev_l;press_count_r;press_time_r;press_time_prev_r"
|
||||
|
||||
press_count_l_input_slot = 1
|
||||
press_time_l_input_slot = 1
|
||||
press_time_prev_l_input_slot = 1
|
||||
press_count_l_mask = 20
|
||||
press_time_l_mask = 20
|
||||
press_time_prev_l_mask = 20
|
||||
press_count_r_input_slot = 1
|
||||
press_time_r_input_slot = 1
|
||||
press_time_prev_r_input_slot = 1
|
||||
press_count_r_mask = 10
|
||||
press_time_r_mask = 10
|
||||
press_time_prev_r_mask = 10
|
||||
|
||||
press_count_l_semantic = transition_count
|
||||
press_time_l_semantic = transition
|
||||
press_time_prev_l_semantic = transition_previous
|
||||
press_count_r_semantic = transition_count
|
||||
press_time_r_semantic = transition
|
||||
press_time_prev_r_semantic = transition_previous
|
||||
|
||||
textures = "border;page1;page2;page3;page4;page5;page6"
|
||||
border = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/manualshaders/manual-reader-border.png"
|
||||
page1 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/manualshaders/page_1.jpg"
|
||||
page2 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/manualshaders/page_2.jpg"
|
||||
page3 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/manualshaders/page_3.jpg"
|
||||
page4 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/manualshaders/page_4.jpg"
|
||||
page5 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/manualshaders/page_5.jpg"
|
||||
page6 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/manualshaders/page_6.jpg"
|
||||
|
||||
border_linear = true
|
||||
page1_linear = true
|
||||
page2_linear = true
|
||||
page3_linear = true
|
||||
page4_linear = true
|
||||
page5_linear = true
|
||||
page6_linear = true
|
255
pkg/USRDIR/gameaware/manual-reader/manual-reader.cg
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
Author: Themaister
|
||||
License: Public domain
|
||||
*/
|
||||
|
||||
// Border shader. 4x input scale, 1920x1080 border. :)
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
float frame_count;
|
||||
};
|
||||
|
||||
struct VERT
|
||||
{
|
||||
float2 menu_pos;
|
||||
float2 menu_pos_alt;
|
||||
float alpha0;
|
||||
float alpha0_alt;
|
||||
float alpha1;
|
||||
float alpha1_alt;
|
||||
float alpha2;
|
||||
float alpha2_alt;
|
||||
float alpha3;
|
||||
float alpha3_alt;
|
||||
float alpha4;
|
||||
float alpha4_alt;
|
||||
float alpha5;
|
||||
float alpha5_alt;
|
||||
};
|
||||
|
||||
#define MENU_PAGE_RES float2(569, 1016.0)
|
||||
#define PAGE_GEOM float2(4.0, 2.0)
|
||||
|
||||
const float box_scale_ = 4.0; // 4x scale.
|
||||
const float2 out_res_ = float2(1920.0, 1080.0); // Output target size.
|
||||
|
||||
// Output resolution on screen for the menu pages. The .jpg/.png can be whatever size.
|
||||
const float2 menu_page_res_ = MENU_PAGE_RES;
|
||||
|
||||
const float2 page_geom = PAGE_GEOM;
|
||||
|
||||
const float2 menu_res_ = PAGE_GEOM * MENU_PAGE_RES;
|
||||
|
||||
// Depends on border. :)
|
||||
const float2 shift_ = float2(-270.0, -54.0);
|
||||
const float2 page_shift_ = float2(588.0, 10.0);
|
||||
|
||||
const float pages = 48.0; // Tweakable.
|
||||
|
||||
float2 pixel_shift(float2 middle, float2 show_size)
|
||||
{
|
||||
return float2(-2.0, 2.0) * middle / show_size;
|
||||
}
|
||||
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
out float4 oPosition : POSITION,
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
float4 color : COLOR,
|
||||
out float4 oColor : COLOR,
|
||||
|
||||
float2 tex : TEXCOORD,
|
||||
out float2 oTex : TEXCOORD,
|
||||
|
||||
float2 tex_border : TEXCOORD1,
|
||||
out float2 otex_border : TEXCOORD1,
|
||||
|
||||
out VERT vout,
|
||||
|
||||
uniform float press_count_l,
|
||||
uniform float press_time_l,
|
||||
uniform float press_time_prev_l,
|
||||
uniform float press_count_r,
|
||||
uniform float press_time_r,
|
||||
uniform float press_time_prev_r,
|
||||
|
||||
uniform input IN
|
||||
)
|
||||
{
|
||||
const float2 out_res = IN.output_size;
|
||||
const float2 scaling_coeff = out_res / out_res_;
|
||||
const float2 box_scale = box_scale_ * scaling_coeff;
|
||||
const float2 menu_page_res = menu_page_res_ * scaling_coeff;
|
||||
const float2 menu_res = menu_res_ * scaling_coeff;
|
||||
const float2 shift = shift_ * scaling_coeff;
|
||||
const float2 page_shift = page_shift_ * scaling_coeff;
|
||||
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
|
||||
float2 scale = (IN.output_size / IN.video_size) / box_scale;
|
||||
float2 middle = 0.5 * IN.video_size / IN.texture_size;
|
||||
float2 diff = tex.xy - middle;
|
||||
oTex = middle + (diff * scale + shift * pixel_shift(middle, IN.video_size * box_scale)) * IN.video_size / float2(256.0, 224.0);
|
||||
middle = float2(0.5, 0.5);
|
||||
float2 dist = tex_border - middle;
|
||||
otex_border = middle + dist * IN.output_size / out_res;
|
||||
|
||||
// Calculate blend time.
|
||||
float time;
|
||||
|
||||
if (press_time_l > press_time_r)
|
||||
{
|
||||
if (floor(fmod(press_count_l, 2.0)) > 0.0)
|
||||
time = (IN.frame_count - press_time_l) / 20.0;
|
||||
else
|
||||
time = (IN.frame_count - press_time_prev_l) / 20.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (floor(fmod(press_count_r, 2.0)) > 0.0)
|
||||
time = (IN.frame_count - press_time_r) / 20.0;
|
||||
else
|
||||
time = (IN.frame_count - press_time_prev_r) / 20.0;
|
||||
}
|
||||
|
||||
float alpha_0 = 0.0;
|
||||
float alpha_0_alt = 0.0;
|
||||
float alpha_1 = 0.0;
|
||||
float alpha_1_alt = 0.0;
|
||||
float alpha_2 = 0.0;
|
||||
float alpha_2_alt = 0.0;
|
||||
float alpha_3 = 0.0;
|
||||
float alpha_3_alt = 0.0;
|
||||
float alpha_4 = 0.0;
|
||||
float alpha_4_alt = 0.0;
|
||||
float alpha_5 = 0.0;
|
||||
float alpha_5_alt = 0.0;
|
||||
|
||||
// Calculate blend coeffs.
|
||||
float page_index = floor(fmod((press_count_r + 1.0) / 2.0, pages)) - floor(fmod((press_count_l + 1.0) / 2.0, pages));
|
||||
if (page_index < 0.0)
|
||||
page_index = pages + page_index;
|
||||
|
||||
float page_index_prev;
|
||||
|
||||
if (press_time_l > press_time_r)
|
||||
{
|
||||
page_index_prev = fmod(page_index + 1.0, pages);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (page_index == 0.0)
|
||||
page_index_prev = pages - 1.0;
|
||||
else
|
||||
page_index_prev = page_index - 1.0;
|
||||
}
|
||||
|
||||
float abs_page_index = floor(page_index / 8.0);
|
||||
float abs_page_index_prev = floor(page_index_prev / 8.0);
|
||||
|
||||
float full_alpha = 1.0 - exp(-time);
|
||||
float prev_alpha = exp(-time);
|
||||
|
||||
if (abs_page_index >= 5.0)
|
||||
alpha_5 = full_alpha;
|
||||
else if (abs_page_index >= 4.0)
|
||||
alpha_4 = full_alpha;
|
||||
else if (abs_page_index >= 3.0)
|
||||
alpha_3 = full_alpha;
|
||||
else if (abs_page_index >= 2.0)
|
||||
alpha_2 = full_alpha;
|
||||
else if (abs_page_index >= 1.0)
|
||||
alpha_1 = full_alpha;
|
||||
else
|
||||
alpha_0 = full_alpha;
|
||||
|
||||
if (abs_page_index_prev >= 5.0)
|
||||
alpha_5_alt = prev_alpha;
|
||||
else if (abs_page_index_prev >= 4.0)
|
||||
alpha_4_alt = prev_alpha;
|
||||
else if (abs_page_index_prev >= 3.0)
|
||||
alpha_3_alt = prev_alpha;
|
||||
else if (abs_page_index_prev >= 2.0)
|
||||
alpha_2_alt = prev_alpha;
|
||||
else if (abs_page_index_prev >= 1.0)
|
||||
alpha_1_alt = prev_alpha;
|
||||
else
|
||||
alpha_0_alt = prev_alpha;
|
||||
|
||||
|
||||
float2 abs_shift = float2(0.5, -0.5) * (page_geom - float2(1.0));
|
||||
abs_shift += float2(-fmod(page_index, page_geom.x), floor(fmod(page_index, page_geom.x * page_geom.y) / page_geom.x));
|
||||
abs_shift *= menu_page_res;
|
||||
|
||||
float2 abs_shift_alt = float2(0.5, -0.5) * (page_geom - float2(1.0));
|
||||
abs_shift_alt += float2(-fmod(page_index_prev, page_geom.x), floor(fmod(page_index_prev, page_geom.x * page_geom.y) / page_geom.x));
|
||||
abs_shift_alt *= menu_page_res;
|
||||
|
||||
float2 menu_pos =
|
||||
middle +
|
||||
dist * IN.output_size / menu_res +
|
||||
(page_shift + abs_shift) * pixel_shift(middle, menu_res);
|
||||
|
||||
float2 menu_pos_alt =
|
||||
middle +
|
||||
dist * IN.output_size / menu_res +
|
||||
(page_shift + abs_shift_alt) * pixel_shift(middle, menu_res);
|
||||
|
||||
vout = VERT(menu_pos, menu_pos_alt,
|
||||
alpha_0, alpha_0_alt,
|
||||
alpha_1, alpha_1_alt,
|
||||
alpha_2, alpha_2_alt,
|
||||
alpha_3, alpha_3_alt,
|
||||
alpha_4, alpha_4_alt,
|
||||
alpha_5, alpha_5_alt
|
||||
);
|
||||
}
|
||||
|
||||
float4 main_fragment (
|
||||
float2 tex : TEXCOORD0, float2 tex_border : TEXCOORD1,
|
||||
uniform sampler2D s0 : TEXUNIT0,
|
||||
|
||||
uniform sampler2D border,
|
||||
uniform sampler2D page1,
|
||||
uniform sampler2D page2,
|
||||
uniform sampler2D page3,
|
||||
uniform sampler2D page4,
|
||||
uniform sampler2D page5,
|
||||
uniform sampler2D page6,
|
||||
in VERT vout) : COLOR
|
||||
{
|
||||
float4 frame = tex2D(s0, tex);
|
||||
float4 background = tex2D(border, tex_border);
|
||||
|
||||
float alpha_mask = 1.0;
|
||||
if (tex_border.x >= 0.999 || tex_border.x < 0.65 || tex_border.y >= 0.999 || tex_border.y <= 0.001)
|
||||
alpha_mask = 0.0;
|
||||
|
||||
return
|
||||
alpha_mask *
|
||||
(
|
||||
tex2D(page1, vout.menu_pos) * vout.alpha0 +
|
||||
tex2D(page1, vout.menu_pos_alt) * vout.alpha0_alt +
|
||||
tex2D(page2, vout.menu_pos) * vout.alpha1 +
|
||||
tex2D(page2, vout.menu_pos_alt) * vout.alpha1_alt +
|
||||
tex2D(page3, vout.menu_pos) * vout.alpha2 +
|
||||
tex2D(page3, vout.menu_pos_alt) * vout.alpha2_alt +
|
||||
tex2D(page4, vout.menu_pos) * vout.alpha3 +
|
||||
tex2D(page4, vout.menu_pos_alt) * vout.alpha3_alt +
|
||||
tex2D(page5, vout.menu_pos) * vout.alpha4 +
|
||||
tex2D(page5, vout.menu_pos_alt) * vout.alpha4_alt +
|
||||
tex2D(page6, vout.menu_pos) * vout.alpha5 +
|
||||
tex2D(page6, vout.menu_pos_alt) * vout.alpha5_alt
|
||||
)
|
||||
|
||||
+ lerp(frame, background, background.a);
|
||||
}
|
||||
|
||||
|
BIN
pkg/USRDIR/gameaware/manual-reader/page_1.jpg
Normal file
After Width: | Height: | Size: 184 KiB |
BIN
pkg/USRDIR/gameaware/manual-reader/page_2.jpg
Normal file
After Width: | Height: | Size: 194 KiB |
BIN
pkg/USRDIR/gameaware/manual-reader/page_3.jpg
Normal file
After Width: | Height: | Size: 203 KiB |
BIN
pkg/USRDIR/gameaware/manual-reader/page_4.jpg
Normal file
After Width: | Height: | Size: 210 KiB |
BIN
pkg/USRDIR/gameaware/manual-reader/page_5.jpg
Normal file
After Width: | Height: | Size: 212 KiB |
BIN
pkg/USRDIR/gameaware/manual-reader/page_6.jpg
Normal file
After Width: | Height: | Size: 204 KiB |
11
pkg/USRDIR/gameaware/mario-water-only-underwater-levels.cfg
Normal file
@ -0,0 +1,11 @@
|
||||
imports = "mario_water;mario_water_time"
|
||||
mario_water_semantic = capture
|
||||
mario_water_time_semantic = transition
|
||||
mario_water_wram = 0085
|
||||
mario_water_time_wram = 0085
|
||||
shaders = 2
|
||||
shader0 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/mario-water.cg"
|
||||
shader1 = "/dev_hdd0/game/SNES90000/USRDIR/shaders/stock.cg"
|
||||
textures = rain
|
||||
rain = "/dev_hdd0/game/SNES90000/USRDIR/borders/Centered-1080p/overlays/none-overlay.png"
|
||||
rain_linear = true
|
11
pkg/USRDIR/gameaware/mario-water.cfg
Normal file
@ -0,0 +1,11 @@
|
||||
imports = "mario_water;mario_water_time"
|
||||
mario_water_semantic = capture
|
||||
mario_water_time_semantic = transition
|
||||
mario_water_wram = 0075
|
||||
mario_water_time_wram = 0075
|
||||
shaders = 2
|
||||
shader0 = "/dev_hdd0/game/SNES90000/USRDIR/gameaware/mario-water.cg"
|
||||
shader1 = "/dev_hdd0/game/SNES90000/USRDIR/shaders/stock.cg"
|
||||
textures = rain
|
||||
rain = "/dev_hdd0/game/SNES90000/USRDIR/borders/Centered-1080p/overlays/none-overlay.png"
|
||||
rain_linear = true
|
107
pkg/USRDIR/gameaware/mario-water.cg
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
Author: Themaister
|
||||
License: Public domain
|
||||
*/
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
float frame_count;
|
||||
};
|
||||
|
||||
struct prev_in
|
||||
{
|
||||
float2 tex_coord;
|
||||
sampler2D texture;
|
||||
};
|
||||
|
||||
struct vertex_out
|
||||
{
|
||||
float water;
|
||||
};
|
||||
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
out float4 oPosition : POSITION,
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
float4 color : COLOR,
|
||||
out float4 oColor : COLOR,
|
||||
|
||||
float2 tex : TEXCOORD0,
|
||||
out float2 oTex : TEXCOORD0,
|
||||
float2 tex1 : TEXCOORD1,
|
||||
out float2 oTex1 : TEXCOORD1,
|
||||
|
||||
out vertex_out VERT,
|
||||
|
||||
uniform float mario_water,
|
||||
uniform float mario_water_time,
|
||||
|
||||
uniform input IN
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
oTex = tex;
|
||||
oTex1 = tex1;
|
||||
float transition_time = (IN.frame_count - mario_water_time) / 120.0;
|
||||
|
||||
float water_coeff;
|
||||
|
||||
if (mario_water > 0.0)
|
||||
water_coeff = 1.0;
|
||||
else
|
||||
water_coeff = exp(-transition_time);
|
||||
|
||||
VERT = vertex_out(water_coeff);
|
||||
}
|
||||
|
||||
const float2 src0 = float2(0.6, 0.7);
|
||||
const float2 src1 = float2(0.9, 0.9);
|
||||
const float2 src2 = float2(-0.6, 0.3);
|
||||
const float2 src3 = float2(0.1, 0.4);
|
||||
const float2 src4 = float2(0.1, 0.4);
|
||||
const float2 src5 = float2(0.5, 0.5);
|
||||
const float2 src6 = float2(-1.0, 1.0);
|
||||
|
||||
float apply_wave(float2 pos, float2 src, float cnt)
|
||||
{
|
||||
float2 diff = pos - src;
|
||||
float dist = 300.0 * sqrt(dot(diff, diff));
|
||||
dist -= 0.15 * cnt;
|
||||
return sin(dist);
|
||||
}
|
||||
|
||||
float4 water_texture(float4 output, float2 scale, float cnt)
|
||||
{
|
||||
float res = apply_wave(scale, src0, cnt);
|
||||
res += apply_wave(scale, src1, cnt);
|
||||
res += apply_wave(scale, src2, cnt);
|
||||
res += apply_wave(scale, src3, cnt);
|
||||
res += apply_wave(scale, src4, cnt);
|
||||
res += apply_wave(scale, src5, cnt);
|
||||
res += apply_wave(scale, src6, cnt);
|
||||
|
||||
return output * (0.95 + 0.012 * res);
|
||||
}
|
||||
|
||||
float4 main_fragment
|
||||
(
|
||||
uniform input IN,
|
||||
float2 tex : TEXCOORD0, uniform sampler2D s0 : TEXUNIT0,
|
||||
uniform sampler2D rain, float2 tex1 : TEXCOORD1,
|
||||
in vertex_out VERT
|
||||
) : COLOR
|
||||
{
|
||||
float4 water_tex = water_texture(tex2D(s0, tex),
|
||||
tex * IN.texture_size / IN.video_size, IN.frame_count);
|
||||
|
||||
float4 normal_tex = tex2D(s0, tex);
|
||||
float4 rain_tex = tex2D(rain, tex1);
|
||||
|
||||
return lerp(lerp(normal_tex, water_tex, VERT.water), rain_tex, rain_tex.a * VERT.water * 0.5);
|
||||
}
|
7
pkg/USRDIR/presets/2xBR-v2-plus-4xSoft-variation-1.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2 + 4xSoft-variation"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/2xBR-v2.cg"
|
||||
PS3CurrentShader2 = "xSoft/4xSoft-variation-1.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2-plus-Bicubic-sharper.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2 + Bicubic-sharper"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "xBR/2xBR-v2.cg"
|
||||
PS3CurrentShader2 = "Bicubic/Bicubic-sharper.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2-plus-Lanczos16.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2 + Lanczos16"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "xBR/2xBR-v2.cg"
|
||||
PS3CurrentShader2 = "Lanczos/Lanczos16.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2-plus-Lanczos4.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2 + Lanczos4"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "xBR/2xBR-v2.cg"
|
||||
PS3CurrentShader2 = "Lanczos/Lanczos4.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2-plus-stock.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2 + stock"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/2xBR-v2.cg"
|
||||
PS3CurrentShader2 = "stock.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2.1-plus-stock.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2.1 + stock"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/2xBR-v2.1.cg"
|
||||
PS3CurrentShader2 = "stock.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2.2-plus-Quilez.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2.2 + Quilez"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/2xBR-v2.2.cg"
|
||||
PS3CurrentShader2 = "Quilez.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2.2-plus-advAA-aspect-10-7.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2.2 + advAA aspect 10:7"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/2xBR-v2.2.cg"
|
||||
PS3CurrentShader2 = "2x-boxed/AdvancedAA-box-2x-aspect-10-7.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2.2-plus-advAA-box.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2.2 + advancedAA box"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/2xBR-v2.2.cg"
|
||||
PS3CurrentShader2 = "2x-boxed/AdvancedAA-box-2.5x.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/2xBR-v2.2-plus-stock.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xBR-v2.2 + stock"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/2xBR-v2.2.cg"
|
||||
PS3CurrentShader2 = "stock.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xSaI + 4xSoft-variation-1 (Sharp)"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "xSaL/2xSaI.cg"
|
||||
PS3CurrentShader2 = "xSoft/4xSoft-variation-1.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
7
pkg/USRDIR/presets/2xsai-plus-4xsoft-variation-1.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "2xSaI + 4xSoft-variation-1"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "xSaL/2xSaI.cg"
|
||||
PS3CurrentShader2 = "xSoft/4xSoft-variation-1.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/3xBR-v2-plus-Quilez.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "3xBR-v2 + Quilez"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/3xBR-v2.cg"
|
||||
PS3CurrentShader2 = "Quilez.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 3
|
7
pkg/USRDIR/presets/3xBR-v2-plus-stock.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "3xBR-v2 + stock"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/3xBR-v2.cg"
|
||||
PS3CurrentShader2 = "stock.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 3
|
7
pkg/USRDIR/presets/3xBR-v2.1-plus-Quilez.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "3xBR-v2.1 + Quilez"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/3xBR-v2.1.cg"
|
||||
PS3CurrentShader2 = "Quilez.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 3
|
7
pkg/USRDIR/presets/3xBR-v2.1-plus-stock.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "3xBR-v2.1 + stock"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/3xBR-v2.1.cg"
|
||||
PS3CurrentShader2 = "stock.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 3
|
7
pkg/USRDIR/presets/4xBR-plus-stock.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "4xBR + stock"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/4xBR.cg"
|
||||
PS3CurrentShader2 = "stock.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
7
pkg/USRDIR/presets/4xBR-v1.1-plus-Quilez.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "4xBR-v1.1 + Quilez"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/4xBR-v1.1.cg"
|
||||
PS3CurrentShader2 = "Quilez.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
7
pkg/USRDIR/presets/4xBR-v1.1-plus-stock.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "4xBR-v1.1 + stock"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xBR/4xBR-v1.1.cg"
|
||||
PS3CurrentShader2 = "stock.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
7
pkg/USRDIR/presets/4xsoft-hd-plus-4xsoft-4x.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "4xSoftHD + 4xSoft (x4)"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "xSoft/4xSoft-HD.cg"
|
||||
PS3CurrentShader2 = "xSoft/4xSoft.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "4xSoftHD + 4xSoftHD-1152x672"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xSoft/4xSoft-HD.cg"
|
||||
PS3CurrentShader2 = "xSoft/4xSoft-HD-1152x672.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
7
pkg/USRDIR/presets/4xsoft-hd-plus-4xsoft-hd-960-592.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "4xSoftHD + 4xSoftHD (960x592)"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "xSoft/4xSoft-HD.cg"
|
||||
PS3CurrentShader2 = "xSoft/4xSoft-HD-960x592.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "4xSoftHD + 4xSoft-variation-1"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "xSoft/4xSoft-HD.cg"
|
||||
PS3CurrentShader2 = "xSoft/4xSoft-variation-1.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
8
pkg/USRDIR/presets/4xsoft-hd-plus-anti-aliasing.conf
Normal file
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD + Anti-aliasing
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD.cg
|
||||
PS3CurrentShader2 = /AdvancedAA.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
8
pkg/USRDIR/presets/4xsoft-hd-plus-crt.conf
Normal file
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD + CRT
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD.cg
|
||||
PS3CurrentShader2 = /CRT/crt.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
8
pkg/USRDIR/presets/4xsoft-hd-plus-scanline.conf
Normal file
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD + Scanline
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD.cg
|
||||
PS3CurrentShader2 = /scanline.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
8
pkg/USRDIR/presets/4xsoft-hd-plus-sharpen.conf
Normal file
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD + Sharpen
|
||||
Smooth = 1
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD.cg
|
||||
PS3CurrentShader2 = /Sharpen/sharpen-light2.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD-variation-1 + 4xSoftHD-1152x672
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD-variation-1.cg
|
||||
PS3CurrentShader2 = /xSoft/4xSoft-HD-1152x672.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD-variation-1 + 4xSoft-HD-960x592
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD-variation-1.cg
|
||||
PS3CurrentShader2 = /xSoft/4xSoft-HD-960x592.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD-variation-1 + 4xSoft-variation-1
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD-variation-1.cg
|
||||
PS3CurrentShader2 = /xSoft/4xSoft-variation-1.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD-variation-1 + Anti-aliasing
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD-variation-1.cg
|
||||
PS3CurrentShader2 = /AdvancedAA.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
8
pkg/USRDIR/presets/4xsoft-hd-variation-1-plus-hq2x.conf
Normal file
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD-variation-1 + HQ2x
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = //4xSoft-HD-variation-1.cg
|
||||
PS3CurrentShader2 = //hq2x.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 4xSoftHD-variation-1 + Scanlines
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = /xSoft/4xSoft-HD-variation-1.cg
|
||||
PS3CurrentShader2 = /scanline.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 4
|
8
pkg/USRDIR/presets/5xBR-v2.1-plus-AdvAA-box.conf
Normal file
@ -0,0 +1,8 @@
|
||||
[PS3General]
|
||||
ShaderPresetTitle = 5xBR-v2.1 plus AdvancedAA
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = /xBR/5xBR-v2.1.cg
|
||||
PS3CurrentShader2 = /1x-boxed/AdvancedAA-box-1x.cg
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 5
|
8
pkg/USRDIR/presets/Borders-Centered-2x-scale.conf
Normal file
@ -0,0 +1,8 @@
|
||||
KeepAspect = 3
|
||||
ShaderPresetTitle = "Borders Centered (2x scale - 1080p)"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "AdvancedAA.cg"
|
||||
PS3CurrentShader2 = "Borders/Border-Centered/border-centered-fbo-scale-2x.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
8
pkg/USRDIR/presets/Borders-Centered-Water-2x-scale.conf
Normal file
@ -0,0 +1,8 @@
|
||||
KeepAspect = 3
|
||||
ShaderPresetTitle = "Borders Centered + Water (2x scale - 1080p)"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "AdvancedAA.cg"
|
||||
PS3CurrentShader2 = "Borders/Border-Centered/border-centered-water-fbo-scale-2x.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
8
pkg/USRDIR/presets/Borders-Left-Portrait-2x-scale.conf
Normal file
@ -0,0 +1,8 @@
|
||||
KeepAspect = 3
|
||||
ShaderPresetTitle = "Borders Left Portrait (2x scale - 1080p)"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "AdvancedAA.cg"
|
||||
PS3CurrentShader2 = "Borders/Border-Left-Portrait/border-left-portrait-fbo-scale-2x.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "Anti-Aliasing + Bicubic Anti-Aliasing (sharper)"
|
||||
Smooth = 0
|
||||
Smooth2 = 1
|
||||
PS3CurrentShader = "AdvancedAA.cg"
|
||||
PS3CurrentShader2 = "Bicubic/Bicubic-sharper.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
7
pkg/USRDIR/presets/anti-aliasing-plus-bloom.conf
Normal file
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "Anti-Aliasing + Bloom"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "AdvancedAA.cg"
|
||||
PS3CurrentShader2 = "Bloom/bloom-HD.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|
@ -0,0 +1,7 @@
|
||||
ShaderPresetTitle = "Anti-Aliasing + CRT High Gamma"
|
||||
Smooth = 0
|
||||
Smooth2 = 0
|
||||
PS3CurrentShader = "AdvancedAA.cg"
|
||||
PS3CurrentShader2 = "CRT/crt-highgamma.cg"
|
||||
ScaleEnabled = 1
|
||||
ScaleFactor = 2
|